/// <summary> /// Determines if a position is located between two caret units. /// </summary> /// <param name="position"> /// Position to test. /// </param> /// <returns> /// Returns true if the specified position precedes or follows /// the first or last code point of a caret unit, respectively. /// </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> /// <remarks> /// In the context of this method, "caret unit" refers to a group /// of one or more Unicode code points that map to a single rendered /// glyph. /// </remarks> internal override bool IsAtCaretUnitBoundary(ITextPointer position) { FixedTextPointer ftp = Container.VerifyPosition(position); FixedPosition fixedp; if (_GetFixedPosition(ftp, out fixedp)) { DependencyObject element = this.FixedPage.GetElement(fixedp.Node); if (element is Glyphs) { Glyphs g = (Glyphs)element; int characterCount = (g.UnicodeString == null ? 0 : g.UnicodeString.Length); if (fixedp.Offset == characterCount) { //end of line -- allow caret return(true); } else { GlyphRun run = g.MeasurementGlyphRun; return(run.CaretStops == null || run.CaretStops[fixedp.Offset]); } } else if (element is Image || element is Path) { //support caret before and after image return(true); } else { // No text position should be on any other type of element Debug.Assert(false); } } return(false); }
// Token: 0x06002EE3 RID: 12003 RVA: 0x000D3B5C File Offset: 0x000D1D5C internal override ITextPointer GetNextCaretUnitPosition(ITextPointer position, LogicalDirection direction) { FixedTextPointer ftp = this.Container.VerifyPosition(position); FixedPosition fixedPosition; if (this._GetFixedPosition(ftp, out fixedPosition)) { DependencyObject element = this.FixedPage.GetElement(fixedPosition.Node); if (element is Glyphs) { Glyphs glyphs = (Glyphs)element; GlyphRun glyphRun = glyphs.ToGlyphRun(); int num = (glyphRun.Characters == null) ? 0 : glyphRun.Characters.Count; CharacterHit characterHit = (fixedPosition.Offset == num) ? new CharacterHit(fixedPosition.Offset - 1, 1) : new CharacterHit(fixedPosition.Offset, 0); CharacterHit obj = (direction == LogicalDirection.Forward) ? glyphRun.GetNextCaretCharacterHit(characterHit) : glyphRun.GetPreviousCaretCharacterHit(characterHit); if (!characterHit.Equals(obj)) { LogicalDirection edge = LogicalDirection.Forward; if (obj.TrailingLength > 0) { edge = LogicalDirection.Backward; } int offset = obj.FirstCharacterIndex + obj.TrailingLength; return(this._CreateTextPointer(new FixedPosition(fixedPosition.Node, offset), edge)); } } } ITextPointer textPointer = position.CreatePointer(); textPointer.MoveToNextInsertionPosition(direction); return(textPointer); }
//-------------------------------------------------------------------- // // 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); }
//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; } }
// Token: 0x06002EE2 RID: 12002 RVA: 0x000D3AB0 File Offset: 0x000D1CB0 internal override bool IsAtCaretUnitBoundary(ITextPointer position) { FixedTextPointer ftp = this.Container.VerifyPosition(position); FixedPosition fixedPosition; if (this._GetFixedPosition(ftp, out fixedPosition)) { DependencyObject element = this.FixedPage.GetElement(fixedPosition.Node); if (element is Glyphs) { Glyphs glyphs = (Glyphs)element; int num = (glyphs.UnicodeString == null) ? 0 : glyphs.UnicodeString.Length; if (fixedPosition.Offset == num) { return(true); } GlyphRun measurementGlyphRun = glyphs.MeasurementGlyphRun; return(measurementGlyphRun.CaretStops == null || measurementGlyphRun.CaretStops[fixedPosition.Offset]); } else if (element is Image || element is Path) { return(true); } } return(false); }
/// <summary> /// <see cref="TextViewBase.GetTightBoundingGeometryFromTextPositions"/> /// </summary> internal override Geometry GetTightBoundingGeometryFromTextPositions(ITextPointer startPosition, ITextPointer endPosition) { PathGeometry boundingGeometry = new PathGeometry(); Debug.Assert(startPosition != null && this.Contains(startPosition)); Debug.Assert(endPosition != null && this.Contains(endPosition)); Dictionary <FixedPage, ArrayList> highlights = new Dictionary <FixedPage, ArrayList>(); FixedTextPointer startftp = this.Container.VerifyPosition(startPosition); FixedTextPointer endftp = this.Container.VerifyPosition(endPosition); this.Container.GetMultiHighlights(startftp, endftp, highlights, FixedHighlightType.TextSelection, null, null); ArrayList highlightList; highlights.TryGetValue(this.FixedPage, out highlightList); if (highlightList != null) { foreach (FixedHighlight fh in highlightList) { if (fh.HighlightType == FixedHighlightType.None) { continue; } Rect backgroundRect = fh.ComputeDesignRect(); if (backgroundRect == Rect.Empty) { continue; } GeneralTransform transform = fh.Element.TransformToAncestor(this.FixedPage); Transform t = transform.AffineTransform; if (t == null) { t = Transform.Identity; } Glyphs g = fh.Glyphs; if (fh.Element.Clip != null) { Rect clipRect = fh.Element.Clip.Bounds; backgroundRect.Intersect(clipRect); } Geometry thisGeometry = new RectangleGeometry(backgroundRect); thisGeometry.Transform = t; backgroundRect = transform.TransformBounds(backgroundRect); boundingGeometry.AddGeometry(thisGeometry); } } return(boundingGeometry); }
//------------------------------------------------------------------- // // Internal Methods // //------------------------------------------------------------------- #region Internal Methods /// <summary> /// Retrieves a position matching a point. /// </summary> /// <param name="point"> /// Point in pixel coordinates to test. /// </param> /// <param name="snapToText"> /// If true, this method must always return a positioned text position /// (the closest position as calculated by the control's heuristics) /// unless the point is outside the boundaries of the page. /// If false, this method should return null position, if the test /// point does not fall within any character bounding box. /// </param> /// <returns> /// A text position and its orientation matching or closest to the point. /// </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 ITextPointer GetTextPositionFromPoint(Point point, bool snapToText) { //Return ITextPointer to the end of this view in this special case if (point.Y == Double.MaxValue && point.X == Double.MaxValue) { FixedPosition fixedp; ITextPointer textPos = this.End; if (_GetFixedPosition(this.End, out fixedp)) { textPos = _CreateTextPointer(fixedp, LogicalDirection.Backward); if (textPos == null) { textPos = this.End; } } return(textPos); } ITextPointer pos = null; UIElement e; bool isHit = _HitTest(point, out e); if (isHit) { Glyphs g = e as Glyphs; if (g != null) { pos = _CreateTextPointerFromGlyphs(g, point); } else if (e is Image) { Image im = (Image)e; FixedPosition fixedp = new FixedPosition(this.FixedPage.CreateFixedNode(this.PageIndex, im), 0); pos = _CreateTextPointer(fixedp, LogicalDirection.Forward); } else if (e is Path) { Path p = (Path)e; if (p.Fill is ImageBrush) { FixedPosition fixedp = new FixedPosition(this.FixedPage.CreateFixedNode(this.PageIndex, p), 0); pos = _CreateTextPointer(fixedp, LogicalDirection.Forward); } } } if (snapToText && pos == null) { pos = _SnapToText(point); Debug.Assert(pos != null); } DocumentsTrace.FixedTextOM.TextView.Trace(string.Format("GetTextPositionFromPoint P{0}, STT={1}, CP={2}", point, snapToText, pos == null ? "null" : ((FixedTextPointer)pos).ToString())); return(pos); }
// Token: 0x06002D3B RID: 11579 RVA: 0x000CC368 File Offset: 0x000CA568 internal Rect ComputeDesignRect() { Glyphs glyphs = this._element as Glyphs; if (glyphs == null) { Image image = this._element as Image; if (image != null && image.Source != null) { return new Rect(0.0, 0.0, image.Width, image.Height); } Path path = this._element as Path; if (path != null) { return path.Data.Bounds; } return Rect.Empty; } else { GlyphRun measurementGlyphRun = glyphs.MeasurementGlyphRun; if (measurementGlyphRun == null || this._gBeginOffset >= this._gEndOffset) { return Rect.Empty; } Rect result = measurementGlyphRun.ComputeAlignmentBox(); result.Offset(glyphs.OriginX, glyphs.OriginY); int num = (measurementGlyphRun.Characters == null) ? 0 : measurementGlyphRun.Characters.Count; double num2 = measurementGlyphRun.GetDistanceFromCaretCharacterHit(new CharacterHit(this._gBeginOffset, 0)); double num3; if (this._gEndOffset == num) { num3 = measurementGlyphRun.GetDistanceFromCaretCharacterHit(new CharacterHit(num - 1, 1)); } else { num3 = measurementGlyphRun.GetDistanceFromCaretCharacterHit(new CharacterHit(this._gEndOffset, 0)); } if (num3 < num2) { double num4 = num2; num2 = num3; num3 = num4; } double width = num3 - num2; if ((measurementGlyphRun.BidiLevel & 1) != 0) { result.X = glyphs.OriginX - num3; } else { result.X = glyphs.OriginX + num2; } result.Width = width; return result; } }
// Token: 0x0600350D RID: 13581 RVA: 0x000F0444 File Offset: 0x000EE644 private string GetText() { double top = this._selectionRect.Top; double bottom = this._selectionRect.Bottom; double left = this._selectionRect.Left; double right = this._selectionRect.Right; double num = 0.0; double num2 = 0.0; int count = this._page.Children.Count; ArrayList arrayList = new ArrayList(); FixedNode[] array = this._panel.FixedContainer.FixedTextBuilder.GetFirstLine(this._pageIndex); while (array != null && array.Length != 0) { RubberbandSelector.TextPositionPair textPositionPair = null; foreach (FixedNode node in array) { Glyphs glyphsElement = this._page.GetGlyphsElement(node); if (glyphsElement != null) { int num3; int charIndex; bool flag; if (this.IntersectGlyphs(glyphsElement, top, left, bottom, right, out num3, out charIndex, out flag, out num, out num2)) { if (textPositionPair == null || num3 > 0) { textPositionPair = new RubberbandSelector.TextPositionPair(); textPositionPair.first = this._GetTextPosition(node, num3); arrayList.Add(textPositionPair); } textPositionPair.second = this._GetTextPosition(node, charIndex); if (!flag) { textPositionPair = null; } } else { textPositionPair = null; } } } int num4 = 1; array = this._panel.FixedContainer.FixedTextBuilder.GetNextLine(array[0], true, ref num4); } string text = ""; foreach (object obj in arrayList) { RubberbandSelector.TextPositionPair textPositionPair2 = (RubberbandSelector.TextPositionPair)obj; text = text + TextRangeBase.GetTextInternal(textPositionPair2.first, textPositionPair2.second) + "\r\n"; } return(text); }
// 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); }
// Token: 0x06002EF4 RID: 12020 RVA: 0x000D4420 File Offset: 0x000D2620 internal static Rect _GetGlyphRunDesignRect(Glyphs g, int charStart, int charEnd) { GlyphRun glyphRun = g.ToGlyphRun(); if (glyphRun == null) { return(Rect.Empty); } Rect result = glyphRun.ComputeAlignmentBox(); result.Offset(glyphRun.BaselineOrigin.X, glyphRun.BaselineOrigin.Y); int num = 0; if (glyphRun.Characters != null) { num = glyphRun.Characters.Count; } else if (g.UnicodeString != null) { num = g.UnicodeString.Length; } if (charStart > num) { charStart = num; } else if (charStart < 0) { charStart = 0; } if (charEnd > num) { charEnd = num; } else if (charEnd < 0) { charEnd = 0; } double num2 = FixedTextView._GetDistanceToCharacter(glyphRun, charStart); double num3 = FixedTextView._GetDistanceToCharacter(glyphRun, charEnd); double width = num3 - num2; if ((glyphRun.BidiLevel & 1) != 0) { result.X = glyphRun.BaselineOrigin.X - num3; } else { result.X = glyphRun.BaselineOrigin.X + num2; } result.Width = width; return(result); }
[Ignore] // this test will cause moonlight to call the plugins onerror handler, which will break all other tests (regressed in r145615) public void FontUri_Backslash_Absolute () { string uri = @"\\server\dir\font.ttf"; Uri u = new Uri (uri); Assert.AreEqual ("file://server/dir/font.ttf", u.ToString (), "Uri-UNC"); Assert.Throws<XamlParseException> (delegate { // the string with backslashes is not acceptable XamlReader.Load (GetXaml (uri)); }, "UNC"); Glyphs g = new Glyphs (); // but an Uri build from it (e.g. without the backslash) is ok g.FontUri = u; }
[Ignore] // this test will cause moonlight to call the plugins onerror handler, which will break all other tests (regressed in ~r146060) public void FontUri_Backslash_Relative () { string uri = @"\font.ttf"; Uri u = new Uri (uri, UriKind.Relative); Assert.AreEqual (uri, u.ToString (), "Uri-single-backslash"); Assert.Throws<XamlParseException> (delegate { // the string with backslashes is not acceptable XamlReader.Load (GetXaml (uri)); }, "single-backslash"); Glyphs g = new Glyphs (); // but an Uri build from it (even with the backslash) is ok g.FontUri = u; }
// Token: 0x06002FD3 RID: 12243 RVA: 0x000D75E4 File Offset: 0x000D57E4 private bool ReadGlyphIndex(string valueSpec, ref bool inCluster, ref int glyphClusterSize, ref int characterClusterSize, ref ushort glyphIndex) { string s = valueSpec; int num = valueSpec.IndexOf('('); if (num != -1) { for (int i = 0; i < num; i++) { if (!char.IsWhiteSpace(valueSpec[i])) { throw new ArgumentException(SR.Get("GlyphsClusterBadCharactersBeforeBracket")); } } if (inCluster) { throw new ArgumentException(SR.Get("GlyphsClusterNoNestedClusters")); } int num2 = valueSpec.IndexOf(')'); if (num2 == -1 || num2 <= num + 1) { throw new ArgumentException(SR.Get("GlyphsClusterNoMatchingBracket")); } int num3 = valueSpec.IndexOf(':'); if (num3 == -1) { string s2 = valueSpec.Substring(num + 1, num2 - (num + 1)); characterClusterSize = int.Parse(s2, CultureInfo.InvariantCulture); glyphClusterSize = 1; } else { if (num3 <= num + 1 || num3 >= num2 - 1) { throw new ArgumentException(SR.Get("GlyphsClusterMisplacedSeparator")); } string s3 = valueSpec.Substring(num + 1, num3 - (num + 1)); characterClusterSize = int.Parse(s3, CultureInfo.InvariantCulture); string s4 = valueSpec.Substring(num3 + 1, num2 - (num3 + 1)); glyphClusterSize = int.Parse(s4, CultureInfo.InvariantCulture); } inCluster = true; s = valueSpec.Substring(num2 + 1); } if (Glyphs.IsEmpty(s)) { return(false); } glyphIndex = ushort.Parse(s, CultureInfo.InvariantCulture); return(true); }
// Token: 0x0600301A RID: 12314 RVA: 0x000D8690 File Offset: 0x000D6890 private void _UpdateHighlightForeground(DrawingContext dc, ArrayList highlights) { foreach (object obj in highlights) { FixedHighlight fixedHighlight = (FixedHighlight)obj; Brush brush = null; if (fixedHighlight.HighlightType != FixedHighlightType.None) { Glyphs glyphs = fixedHighlight.Glyphs; if (glyphs != null) { Rect rect = fixedHighlight.ComputeDesignRect(); if (!(rect == Rect.Empty)) { GeneralTransform generalTransform = fixedHighlight.Element.TransformToAncestor(this._page); Transform affineTransform = generalTransform.AffineTransform; if (affineTransform != null) { dc.PushTransform(affineTransform); } else { dc.PushTransform(Transform.Identity); } dc.PushClip(new RectangleGeometry(rect)); if (fixedHighlight.HighlightType == FixedHighlightType.TextSelection) { brush = SelectionHighlightInfo.ForegroundBrush; } else if (fixedHighlight.HighlightType == FixedHighlightType.AnnotationHighlight) { brush = fixedHighlight.ForegroundBrush; } GlyphRun glyphRun = glyphs.ToGlyphRun(); if (brush == null) { brush = glyphs.Fill; } dc.PushGuidelineY1(glyphRun.BaselineOrigin.Y); dc.PushClip(glyphs.Clip); dc.DrawGlyphRun(brush, glyphRun); dc.Pop(); dc.Pop(); dc.Pop(); dc.Pop(); } } } } }
// Token: 0x06002EDE RID: 11998 RVA: 0x000D3528 File Offset: 0x000D1728 internal override ITextPointer GetTextPositionFromPoint(Point point, bool snapToText) { if (point.Y == 1.7976931348623157E+308 && point.X == 1.7976931348623157E+308) { ITextPointer textPointer = this.End; FixedPosition fixedPosition; if (this._GetFixedPosition(this.End, out fixedPosition)) { textPointer = this._CreateTextPointer(fixedPosition, LogicalDirection.Backward); if (textPointer == null) { textPointer = this.End; } } return(textPointer); } ITextPointer textPointer2 = null; UIElement uielement; bool flag = this._HitTest(point, out uielement); if (flag) { Glyphs glyphs = uielement as Glyphs; if (glyphs != null) { textPointer2 = this._CreateTextPointerFromGlyphs(glyphs, point); } else if (uielement is Image) { Image e = (Image)uielement; FixedPosition fixedPosition2 = new FixedPosition(this.FixedPage.CreateFixedNode(this.PageIndex, e), 0); textPointer2 = this._CreateTextPointer(fixedPosition2, LogicalDirection.Forward); } else if (uielement is Path) { Path path = (Path)uielement; if (path.Fill is ImageBrush) { FixedPosition fixedPosition3 = new FixedPosition(this.FixedPage.CreateFixedNode(this.PageIndex, path), 0); textPointer2 = this._CreateTextPointer(fixedPosition3, LogicalDirection.Forward); } } } if (snapToText && textPointer2 == null) { textPointer2 = this._SnapToText(point); } return(textPointer2); }
// Token: 0x06002EF9 RID: 12025 RVA: 0x000D4780 File Offset: 0x000D2980 private ITextPointer _CreateTextPointerFromGlyphs(Glyphs g, Point point) { GeneralTransform generalTransform = this.VisualRoot.TransformToDescendant(g); if (generalTransform != null) { generalTransform.TryTransform(point, out point); } int offset; LogicalDirection edge; this._GlyphRunHitTest(g, point.X, out offset, out edge); FixedPosition fixedPosition = new FixedPosition(this.FixedPage.CreateFixedNode(this.PageIndex, g), offset); return(this._CreateTextPointer(fixedPosition, edge)); }
// Create a text position from description of a fixed position. // This is primarily called from HitTesting code private ITextPointer _CreateTextPointerFromGlyphs(Glyphs g, Point point) { GeneralTransform transform = this.VisualRoot.TransformToDescendant(g); if (transform != null) { transform.TryTransform(point, out point); } int charIndex; LogicalDirection edge; _GlyphRunHitTest(g, point.X, out charIndex, out edge); FixedPosition fixedp = new FixedPosition(this.FixedPage.CreateFixedNode(this.PageIndex, g), charIndex); return(_CreateTextPointer(fixedp, edge)); }
// Token: 0x06002EE0 RID: 12000 RVA: 0x000D382C File Offset: 0x000D1A2C internal override Geometry GetTightBoundingGeometryFromTextPositions(ITextPointer startPosition, ITextPointer endPosition) { PathGeometry pathGeometry = new PathGeometry(); Dictionary <FixedPage, ArrayList> dictionary = new Dictionary <FixedPage, ArrayList>(); FixedTextPointer start = this.Container.VerifyPosition(startPosition); FixedTextPointer end = this.Container.VerifyPosition(endPosition); this.Container.GetMultiHighlights(start, end, dictionary, FixedHighlightType.TextSelection, null, null); ArrayList arrayList; dictionary.TryGetValue(this.FixedPage, out arrayList); if (arrayList != null) { foreach (object obj in arrayList) { FixedHighlight fixedHighlight = (FixedHighlight)obj; if (fixedHighlight.HighlightType != FixedHighlightType.None) { Rect rect = fixedHighlight.ComputeDesignRect(); if (!(rect == Rect.Empty)) { GeneralTransform generalTransform = fixedHighlight.Element.TransformToAncestor(this.FixedPage); Transform transform = generalTransform.AffineTransform; if (transform == null) { transform = Transform.Identity; } Glyphs glyphs = fixedHighlight.Glyphs; if (fixedHighlight.Element.Clip != null) { Rect bounds = fixedHighlight.Element.Clip.Bounds; rect.Intersect(bounds); } Geometry geometry = new RectangleGeometry(rect); geometry.Transform = transform; rect = generalTransform.TransformBounds(rect); pathGeometry.AddGeometry(geometry); } } } } return(pathGeometry); }
/// <summary> /// Finds the next position at the edge of a caret unit in /// specified direction. /// </summary> /// <param name="position"> /// Initial text position of an object/character. /// </param> /// <param name="direction"> /// If Forward, this method returns the "caret unit" position following /// the initial position. /// If Backward, this method returns the caret unit" position preceding /// the initial position. /// </param> /// <returns> /// The next caret unit break position in specified direction. /// </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> /// <remarks> /// In the context of this method, "caret unit" refers to a group of one /// or more Unicode code points that map to a single rendered glyph. /// /// If position is located between two caret units, this method returns /// a new position located at the opposite edge of the caret unit in /// the indicated direction. /// If position is located within a group of Unicode code points that map /// to a single caret unit, this method returns a new position at /// the indicated edge of the containing caret unit. /// If position is located at the beginning of end of content -- there is /// no content in the indicated direction -- then this method returns /// a position located at the same location as initial position. /// </remarks> internal override ITextPointer GetNextCaretUnitPosition(ITextPointer position, LogicalDirection direction) { FixedTextPointer ftp = Container.VerifyPosition(position); FixedPosition fixedp; if (_GetFixedPosition(ftp, out fixedp)) { DependencyObject element = this.FixedPage.GetElement(fixedp.Node); if (element is Glyphs) { Glyphs g = (Glyphs)element; GlyphRun run = g.ToGlyphRun(); int characterCount = (run.Characters == null) ? 0 : run.Characters.Count; CharacterHit start = (fixedp.Offset == characterCount) ? new CharacterHit(fixedp.Offset - 1, 1) : new CharacterHit(fixedp.Offset, 0); CharacterHit next = (direction == LogicalDirection.Forward) ? run.GetNextCaretCharacterHit(start) : run.GetPreviousCaretCharacterHit(start); if (!start.Equals(next)) { LogicalDirection edge = LogicalDirection.Forward; if (next.TrailingLength > 0) { edge = LogicalDirection.Backward; } int index = next.FirstCharacterIndex + next.TrailingLength; return(_CreateTextPointer(new FixedPosition(fixedp.Node, index), edge)); } } } //default behavior is to simply move textpointer ITextPointer pointer = position.CreatePointer(); pointer.MoveToNextInsertionPosition(direction); return(pointer); }
// Token: 0x06002EF0 RID: 12016 RVA: 0x000D3F34 File Offset: 0x000D2134 private void _GlyphRunHitTest(Glyphs g, double xoffset, out int charIndex, out LogicalDirection edge) { charIndex = 0; edge = LogicalDirection.Forward; GlyphRun glyphRun = g.ToGlyphRun(); double distance; if ((glyphRun.BidiLevel & 1) != 0) { distance = glyphRun.BaselineOrigin.X - xoffset; } else { distance = xoffset - glyphRun.BaselineOrigin.X; } bool flag; CharacterHit caretCharacterHitFromDistance = glyphRun.GetCaretCharacterHitFromDistance(distance, out flag); charIndex = caretCharacterHitFromDistance.FirstCharacterIndex + caretCharacterHitFromDistance.TrailingLength; edge = ((caretCharacterHitFromDistance.TrailingLength > 0) ? LogicalDirection.Backward : LogicalDirection.Forward); }
private void _GlyphRunHitTest(Glyphs g, double xoffset, out int charIndex, out LogicalDirection edge) { charIndex = 0; edge = LogicalDirection.Forward; GlyphRun run = g.ToGlyphRun(); bool isInside; double distance; if ((run.BidiLevel & 1) != 0) { distance = run.BaselineOrigin.X - xoffset; } else { distance = xoffset - run.BaselineOrigin.X; } CharacterHit hit = run.GetCaretCharacterHitFromDistance(distance, out isInside); charIndex = hit.FirstCharacterIndex + hit.TrailingLength; edge = (hit.TrailingLength > 0) ? LogicalDirection.Backward : LogicalDirection.Forward; }
/// <summary> /// Retrieves the height and offset, in pixels, of the edge of /// the object/character represented by position. /// </summary> /// <param name="position"> /// Position of an object/character. /// </param> /// <param name="transform"> /// Transform to be applied to returned rect /// </param> /// <returns> /// The height, in pixels, of the edge of the object/character /// represented by position. /// </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> /// <remarks> /// Rect.Width is always 0. /// Output parameter Transform is always Identity. It is not expected that editing scenarios /// will require speparate transform with raw rectangle for this case. /// If the document is empty, then this method returns the expected /// height of a character, if placed at the specified position. /// </remarks> internal override Rect GetRawRectangleFromTextPosition(ITextPointer position, out Transform transform) { #if DEBUG DocumentsTrace.FixedTextOM.TextView.Trace(string.Format("GetRectFromTextPosition {0}, {1}", (FixedTextPointer)position, position.LogicalDirection)); #endif FixedTextPointer ftp = Container.VerifyPosition(position); FixedPosition fixedp; // need a default caret size, otherwise infinite corners cause text editor and MultiPageTextView problems. // Initialize transform to Identity. This function always returns Identity transform. Rect designRect = new Rect(0, 0, 0, 10); transform = Transform.Identity; Debug.Assert(ftp != null); if (ftp.FlowPosition.IsBoundary) { if (!_GetFirstFixedPosition(ftp, out fixedp)) { return(designRect); } } else if (!_GetFixedPosition(ftp, out fixedp)) { // // This is the start/end element, we need to find out the next element and return the next element // start offset/height. // if (position.GetPointerContext(LogicalDirection.Forward) != TextPointerContext.None) { ITextPointer psNext = position.CreatePointer(1); FixedTextPointer ftpNext = Container.VerifyPosition(psNext); if (!_GetFixedPosition(ftpNext, out fixedp)) { return(designRect); } } else { return(designRect); } } if (fixedp.Page != this.PageIndex) { return(designRect); } DependencyObject element = this.FixedPage.GetElement(fixedp.Node); if (element is Glyphs) { Glyphs g = (Glyphs)element; designRect = _GetGlyphRunDesignRect(g, fixedp.Offset, fixedp.Offset); // need to do transform GeneralTransform tran = g.TransformToAncestor(this.FixedPage); designRect = _GetTransformedCaretRect(tran, designRect.TopLeft, designRect.Height); } else if (element is Image) { Image image = (Image)element; GeneralTransform tran = image.TransformToAncestor(this.FixedPage); Point offset = new Point(0, 0); if (fixedp.Offset > 0) { offset.X += image.ActualWidth; } designRect = _GetTransformedCaretRect(tran, offset, image.ActualHeight); } else if (element is Path) { Path path = (Path)element; GeneralTransform tran = path.TransformToAncestor(this.FixedPage); Rect bounds = path.Data.Bounds; Point offset = bounds.TopLeft; if (fixedp.Offset > 0) { offset.X += bounds.Width; } designRect = _GetTransformedCaretRect(tran, offset, bounds.Height); } return(designRect); }
// char index == -1 implies end of run. internal static Rect _GetGlyphRunDesignRect(Glyphs g, int charStart, int charEnd) { GlyphRun run = g.ToGlyphRun(); if (run == null) { return(Rect.Empty); } Rect designRect = run.ComputeAlignmentBox(); designRect.Offset(run.BaselineOrigin.X, run.BaselineOrigin.Y); int charCount = 0; if (run.Characters != null) { charCount = run.Characters.Count; } else if (g.UnicodeString != null) { charCount = g.UnicodeString.Length; } if (charStart > charCount) { //Extra space was added at the end of the run for contiguity Debug.Assert(charStart - charCount == 1); charStart = charCount; } else if (charStart < 0) { //This is a reversed run charStart = 0; } if (charEnd > charCount) { //Extra space was added at the end of the run for contiguity Debug.Assert(charEnd - charCount == 1); charEnd = charCount; } else if (charEnd < 0) { //This is a reversed run charEnd = 0; } double x1 = _GetDistanceToCharacter(run, charStart); double x2 = _GetDistanceToCharacter(run, charEnd); double width = x2 - x1; if ((run.BidiLevel & 1) != 0) { // right to left designRect.X = run.BaselineOrigin.X - x2; } else { designRect.X = run.BaselineOrigin.X + x1; } designRect.Width = width; return(designRect); }
//determines whether and where a rectangle intersects a Glyphs private bool IntersectGlyphs(Glyphs g, double top, double left, double bottom, double right, out int begin, out int end, out bool includeEnd, out double baseline, out double height) { begin = 0; end = 0; includeEnd = false; GlyphRun run = g.ToGlyphRun(); Rect boundingRect = run.ComputeAlignmentBox(); boundingRect.Offset(run.BaselineOrigin.X, run.BaselineOrigin.Y); //useful for same line detection baseline = run.BaselineOrigin.Y; height = boundingRect.Height; double centerLine = boundingRect.Y + .5 * boundingRect.Height; GeneralTransform t = g.TransformToAncestor(_page); Point pt1; t.TryTransform(new Point(boundingRect.Left, centerLine), out pt1); Point pt2; t.TryTransform(new Point(boundingRect.Right, centerLine), out pt2); double dStart, dEnd; bool cross = false; if (pt1.X < left) { if (pt2.X < left) { return false; } cross = true; } else if (pt1.X > right) { if (pt2.X > right) { return false; } cross = true; } else if (pt2.X < left || pt2.X > right) { cross = true; } if (cross) { double d1 = (left - pt1.X) / (pt2.X - pt1.X); double d2 = (right - pt1.X) / (pt2.X - pt1.X); if (d2 > d1) { dStart = d1; dEnd = d2; } else { dStart = d2; dEnd = d1; } } else { dStart = 0; dEnd = 1; } cross = false; if (pt1.Y < top) { if (pt2.Y < top) { return false; } cross = true; } else if (pt1.Y > bottom) { if (pt2.Y > bottom) { return false; } cross = true; } else if (pt2.Y < top || pt2.Y > bottom) { cross = true; } if (cross) { double d1 = (top - pt1.Y) / (pt2.Y - pt1.Y); double d2 = (bottom - pt1.Y) / (pt2.Y - pt1.Y); if (d2 > d1) { if (d1 > dStart) { dStart = d1; } if (d2 < dEnd) { dEnd = d2; } } else { if (d2 > dStart) { dStart = d2; } if (d1 < dEnd) { dEnd = d1; } } } dStart = boundingRect.Left + boundingRect.Width * dStart; dEnd = boundingRect.Left + boundingRect.Width * dEnd; bool leftToRight = ((run.BidiLevel & 1) == 0); begin = GlyphRunHitTest(run, dStart, leftToRight); end = GlyphRunHitTest(run, dEnd, leftToRight); if (begin > end) { int temp = begin; begin = end; end = temp; } Debug.Assert(end >= begin); int characterCount = (run.Characters == null) ? 0 : run.Characters.Count; includeEnd = (end == characterCount); return true; }
/// <summary> /// Initializes all general pens and brushes. /// </summary> private void InitializeResources() { textBrush = new SolidColorBrush(System.Windows.Media.Color.FromRgb(120, 120, 120)); textBrush.Freeze(); Brush gridLineBrush = new SolidColorBrush(System.Windows.Media.Color.FromRgb(160, 160, 160)); ; gridLineBrush.Freeze(); gridLinePen = new Pen(gridLineBrush, 1); gridLinePen.Freeze(); Brush gridBoldLineBrush = new SolidColorBrush(System.Windows.Media.Color.FromRgb(20, 20, 20)); gridBoldLineBrush.Freeze(); gridBoldLinePen = new Pen(gridBoldLineBrush, 1); gridZeroLinePen = new Pen(gridBoldLineBrush, 2); gridBoldLinePen.Freeze(); gridZeroLinePen.Freeze(); backgroundBrush = new SolidColorBrush(System.Windows.Media.Color.FromArgb(0, 48, 48, 48)); backgroundBrush.Freeze(); glyphs = new Glyphs(); glyphs.FontUri = new Uri(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Fonts) + "\\Arial.TTF"); glyphs.FontRenderingEmSize = 11; glyphs.StyleSimulations = StyleSimulations.None; // Seek Needle Brush seekNeedleBrush = Brushes.Red; Pen seekNeedlePen = new Pen(Brushes.Black, 1); seekNeedlePen.Freeze(); SeekNeedle = new GeometryDrawing(); PathGeometry path = new PathGeometry(); path.Figures.Add(new PathFigure( new System.Windows.Point(-4, 0), new[] { new PolyLineSegment(new [] { new System.Windows.Point(4, 0), new System.Windows.Point(0, -7), new System.Windows.Point(0, -20), new System.Windows.Point(0, -7)}, true) }, true)); SeekNeedle.Geometry = path; SeekNeedle.Brush = seekNeedleBrush; SeekNeedle.Pen = seekNeedlePen; }
//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); } }
private void WriteInnerElement(Glyphs glyphs, string typeName) { //TODO: implement }
//determines whether and where a rectangle intersects a Glyphs private bool IntersectGlyphs(Glyphs g, double top, double left, double bottom, double right, out int begin, out int end, out bool includeEnd, out double baseline, out double height) { begin = 0; end = 0; includeEnd = false; GlyphRun run = g.ToGlyphRun(); Rect boundingRect = run.ComputeAlignmentBox(); boundingRect.Offset(run.BaselineOrigin.X, run.BaselineOrigin.Y); //useful for same line detection baseline = run.BaselineOrigin.Y; height = boundingRect.Height; double centerLine = boundingRect.Y + .5 * boundingRect.Height; GeneralTransform t = g.TransformToAncestor(_page); Point pt1; t.TryTransform(new Point(boundingRect.Left, centerLine), out pt1); Point pt2; t.TryTransform(new Point(boundingRect.Right, centerLine), out pt2); double dStart, dEnd; bool cross = false; if (pt1.X < left) { if (pt2.X < left) { return(false); } cross = true; } else if (pt1.X > right) { if (pt2.X > right) { return(false); } cross = true; } else if (pt2.X < left || pt2.X > right) { cross = true; } if (cross) { double d1 = (left - pt1.X) / (pt2.X - pt1.X); double d2 = (right - pt1.X) / (pt2.X - pt1.X); if (d2 > d1) { dStart = d1; dEnd = d2; } else { dStart = d2; dEnd = d1; } } else { dStart = 0; dEnd = 1; } cross = false; if (pt1.Y < top) { if (pt2.Y < top) { return(false); } cross = true; } else if (pt1.Y > bottom) { if (pt2.Y > bottom) { return(false); } cross = true; } else if (pt2.Y < top || pt2.Y > bottom) { cross = true; } if (cross) { double d1 = (top - pt1.Y) / (pt2.Y - pt1.Y); double d2 = (bottom - pt1.Y) / (pt2.Y - pt1.Y); if (d2 > d1) { if (d1 > dStart) { dStart = d1; } if (d2 < dEnd) { dEnd = d2; } } else { if (d2 > dStart) { dStart = d2; } if (d1 < dEnd) { dEnd = d1; } } } dStart = boundingRect.Left + boundingRect.Width * dStart; dEnd = boundingRect.Left + boundingRect.Width * dEnd; bool leftToRight = ((run.BidiLevel & 1) == 0); begin = GlyphRunHitTest(run, dStart, leftToRight); end = GlyphRunHitTest(run, dEnd, leftToRight); if (begin > end) { int temp = begin; begin = end; end = temp; } Debug.Assert(end >= begin); int characterCount = (run.Characters == null) ? 0 : run.Characters.Count; includeEnd = (end == characterCount); return(true); }
//-------------------------------------------------------------------- // // 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; }
//-------------------------------------------------------------------- // // 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)) { run._isReversed = true; run.Text = string.Create(run.Text.Length, run.Text, (destination, runText) => { for (int i = 0; i < destination.Length; i++) { destination[i] = runText[runText.Length - 1 - i]; } }); } 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); }
internal void RenderFixedNode(DrawingContext dc) { // //Iterate through fix node to draw red dotted line // CultureInfo EnglishCulture = System.Windows.Markup.TypeConverterHelper.InvariantEnglishUS; int lineCount = _lineResults.Length; if (lineCount == 0) { return; } FixedNode fixedStartPage = _lineResults[0].Start; FixedNode fixedEndPage = _lineResults[lineCount - 1].End; FixedNode[] fixedNodes = _fixedTextBuilder.FixedFlowMap.FixedOrderGetRangeNodes(fixedStartPage, fixedEndPage); FixedPage fp = _fixedTextBuilder.FixedTextContainer.FixedDocument.GetFixedPage(PageIndex); FormattedText ft; Point prevTextPoint = new Point(0, 0); DpiScale dpi = fp.GetDpi(); foreach (FixedNode currentFixedNode in fixedNodes) { if (currentFixedNode.Page == FixedFlowMap.FixedOrderStartPage) { prevTextPoint.X = prevTextPoint.Y = 0; ft = new FormattedText("FixedOrderStartPage", EnglishCulture, FlowDirection.LeftToRight, new Typeface("Courier New"), 8, Brushes.DarkViolet, dpi.PixelsPerDip); dc.DrawText(ft, prevTextPoint); continue; } if (currentFixedNode.Page == FixedFlowMap.FixedOrderEndPage) { prevTextPoint.X = fp.Width - 100; prevTextPoint.Y = fp.Height - 10; ft = new FormattedText("FixedOrderEndPage", EnglishCulture, FlowDirection.LeftToRight, new Typeface("Courier New"), 8, Brushes.DarkViolet, dpi.PixelsPerDip); dc.DrawText(ft, prevTextPoint); continue; } if (currentFixedNode[1] == FixedFlowMap.FixedOrderStartVisual || currentFixedNode[1] == FixedFlowMap.FixedOrderEndVisual) { prevTextPoint.X = 2; prevTextPoint.Y = prevTextPoint.Y + 10; String outputString = currentFixedNode[1] == FixedFlowMap.FixedOrderStartVisual ? "FixedOrderStartVisual" : "FixedOrderEndVisual"; ft = new FormattedText(outputString, EnglishCulture, FlowDirection.LeftToRight, new Typeface("Courier New"), 8, Brushes.DarkViolet, dpi.PixelsPerDip); dc.DrawText(ft, prevTextPoint); continue; } DependencyObject dependencyObject = fp.GetElement(currentFixedNode); Image image = dependencyObject as Image; if (image != null) { GeneralTransform transform = image.TransformToAncestor(fp); // You can't use GetContentBounds inside OnRender Rect boundingRect = new Rect(0, 0, image.Width, image.Height); Rect imageRect = transform.TransformBounds(boundingRect); if (!imageRect.IsEmpty) { // Image might overlap, inflate the box. imageRect.Inflate(1, 1); Pen pen = new Pen(Brushes.DarkMagenta, 1.5); DrawRectOutline(dc, pen, imageRect); prevTextPoint.X = imageRect.Right; prevTextPoint.Y = imageRect.Bottom - 10; } else { prevTextPoint.X = 2; prevTextPoint.Y = prevTextPoint.Y + 10; } ft = new FormattedText(currentFixedNode.ToString(), EnglishCulture, FlowDirection.LeftToRight, new Typeface("Courier New"), 8, Brushes.DarkViolet, dpi.PixelsPerDip); dc.DrawText(ft, prevTextPoint); continue; } Path path = dependencyObject as Path; if (path != null) { GeneralTransform transform = path.TransformToAncestor(fp); // You can't use GetContentBounds inside OnRender Rect boundingRect = path.Data.Bounds; Rect imageRect = transform.TransformBounds(boundingRect); if (!imageRect.IsEmpty) { // Image might overlap, inflate the box. imageRect.Inflate(1, 1); Pen pen = new Pen(Brushes.DarkMagenta, 1.5); DrawRectOutline(dc, pen, imageRect); prevTextPoint.X = imageRect.Right; prevTextPoint.Y = imageRect.Bottom - 10; } else { prevTextPoint.X = 2; prevTextPoint.Y = prevTextPoint.Y + 10; } ft = new FormattedText(currentFixedNode.ToString(), EnglishCulture, FlowDirection.LeftToRight, new Typeface("Courier New"), 8, Brushes.DarkViolet, dpi.PixelsPerDip); dc.DrawText(ft, prevTextPoint); continue; } Glyphs glyphs = dependencyObject as Glyphs; if (glyphs != null) { GlyphRun run = glyphs.ToGlyphRun(); if (run != null) { Rect glyphBox = run.ComputeAlignmentBox(); glyphBox.Offset(glyphs.OriginX, glyphs.OriginY); GeneralTransform transform = glyphs.TransformToAncestor(fp); // // Draw it using the dotted red line // Pen pen = new Pen(Brushes.Red, 0.5); Transform t = transform.AffineTransform; if (t != null) { dc.PushTransform(t); } else { dc.PushTransform(Transform.Identity); } DrawRectOutline(dc, pen, glyphBox); prevTextPoint.X = glyphBox.Right; prevTextPoint.Y = glyphBox.Bottom; transform.TryTransform(prevTextPoint, out prevTextPoint); dc.Pop(); // transform } else { prevTextPoint.X = 2; prevTextPoint.Y = prevTextPoint.Y + 10; } ft = new FormattedText(currentFixedNode.ToString(), EnglishCulture, FlowDirection.LeftToRight, new Typeface("Courier New"), 8, Brushes.DarkViolet, dpi.PixelsPerDip); dc.DrawText(ft, prevTextPoint); continue; } // // For anything else, there is this code to draw ... // prevTextPoint.X = 2; prevTextPoint.Y = prevTextPoint.Y + 10; ft = new FormattedText(currentFixedNode.ToString(), EnglishCulture, FlowDirection.LeftToRight, new Typeface("Courier New"), 8, Brushes.DarkViolet, dpi.PixelsPerDip); dc.DrawText(ft, prevTextPoint); } }
// Create a text position from description of a fixed position. // This is primarily called from HitTesting code private ITextPointer _CreateTextPointerFromGlyphs(Glyphs g, Point point) { GeneralTransform transform = this.VisualRoot.TransformToDescendant(g); if (transform != null) { transform.TryTransform(point, out point); } int charIndex; LogicalDirection edge; _GlyphRunHitTest(g, point.X, out charIndex, out edge); FixedPosition fixedp = new FixedPosition(this.FixedPage.CreateFixedNode(this.PageIndex, g), charIndex); return _CreateTextPointer(fixedp, edge); }
// char index == -1 implies end of run. internal static Rect _GetGlyphRunDesignRect(Glyphs g, int charStart, int charEnd) { GlyphRun run = g.ToGlyphRun(); if (run == null) { return Rect.Empty; } Rect designRect = run.ComputeAlignmentBox(); designRect.Offset(run.BaselineOrigin.X, run.BaselineOrigin.Y); int charCount = 0; if (run.Characters != null) { charCount = run.Characters.Count; } else if (g.UnicodeString != null) { charCount = g.UnicodeString.Length; } if (charStart > charCount) { //Extra space was added at the end of the run for contiguity Debug.Assert(charStart - charCount == 1); charStart = charCount; } else if (charStart < 0) { //This is a reversed run charStart = 0; } if (charEnd > charCount) { //Extra space was added at the end of the run for contiguity Debug.Assert(charEnd - charCount == 1); charEnd = charCount; } else if (charEnd < 0) { //This is a reversed run charEnd = 0; } double x1 = _GetDistanceToCharacter(run, charStart); double x2 = _GetDistanceToCharacter(run, charEnd); double width = x2 - x1; if ((run.BidiLevel & 1) != 0) { // right to left designRect.X = run.BaselineOrigin.X - x2; } else { designRect.X = run.BaselineOrigin.X + x1; } designRect.Width = width; return designRect; }
public GlyphData(Glyphs glyphs) { Glyphs = glyphs; LowerCaseText = glyphs.UnicodeString.ToLower(); }
/// <summary> /// 在指定点画出文字 /// </summary> /// <param name="s">所画的文字内容</param> /// <param name="p">文字坐标</param> /// <param name="fontsize">文字大小</param> /// <returns>返回文字形状</returns> private GlyphRun DataGraphPrintText(string s, Point p, int fontsize) { Glyphs text = new Glyphs(); text.OriginX = p.X; text.OriginY = p.Y; text.UnicodeString = s; text.FontUri = new Uri(FONT_URI); text.FontRenderingEmSize = fontsize; return text.ToGlyphRun(); }
//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); } }
void System.Windows.Markup.IComponentConnector.Connect(int connectionId, object target) { switch (connectionId) { case 1: this.ThemeGlyph = ((System.Windows.Documents.Glyphs)(target)); #line 43 "..\..\..\Windows\ElysiumView.xaml" this.ThemeGlyph.Initialized += new System.EventHandler(this.ThemeGlyphInitialized); #line default #line hidden return; case 2: #line 52 "..\..\..\Windows\ElysiumView.xaml" ((System.Windows.Controls.MenuItem)(target)).Click += new System.Windows.RoutedEventHandler(this.LightClick); #line default #line hidden return; case 3: #line 54 "..\..\..\Windows\ElysiumView.xaml" ((System.Windows.Controls.MenuItem)(target)).Click += new System.Windows.RoutedEventHandler(this.DarkClick); #line default #line hidden return; case 4: this.AccentGlyph = ((System.Windows.Documents.Glyphs)(target)); #line 61 "..\..\..\Windows\ElysiumView.xaml" this.AccentGlyph.Initialized += new System.EventHandler(this.AccentGlyphInitialized); #line default #line hidden return; case 5: #line 70 "..\..\..\Windows\ElysiumView.xaml" ((System.Windows.Controls.MenuItem)(target)).Click += new System.Windows.RoutedEventHandler(this.AccentClick); #line default #line hidden return; case 6: #line 77 "..\..\..\Windows\ElysiumView.xaml" ((System.Windows.Controls.MenuItem)(target)).Click += new System.Windows.RoutedEventHandler(this.AccentClick); #line default #line hidden return; case 7: #line 84 "..\..\..\Windows\ElysiumView.xaml" ((System.Windows.Controls.MenuItem)(target)).Click += new System.Windows.RoutedEventHandler(this.AccentClick); #line default #line hidden return; case 8: #line 91 "..\..\..\Windows\ElysiumView.xaml" ((System.Windows.Controls.MenuItem)(target)).Click += new System.Windows.RoutedEventHandler(this.AccentClick); #line default #line hidden return; case 9: #line 98 "..\..\..\Windows\ElysiumView.xaml" ((System.Windows.Controls.MenuItem)(target)).Click += new System.Windows.RoutedEventHandler(this.AccentClick); #line default #line hidden return; case 10: #line 105 "..\..\..\Windows\ElysiumView.xaml" ((System.Windows.Controls.MenuItem)(target)).Click += new System.Windows.RoutedEventHandler(this.AccentClick); #line default #line hidden return; case 11: #line 112 "..\..\..\Windows\ElysiumView.xaml" ((System.Windows.Controls.MenuItem)(target)).Click += new System.Windows.RoutedEventHandler(this.AccentClick); #line default #line hidden return; case 12: #line 119 "..\..\..\Windows\ElysiumView.xaml" ((System.Windows.Controls.MenuItem)(target)).Click += new System.Windows.RoutedEventHandler(this.AccentClick); #line default #line hidden return; case 13: #line 126 "..\..\..\Windows\ElysiumView.xaml" ((System.Windows.Controls.MenuItem)(target)).Click += new System.Windows.RoutedEventHandler(this.AccentClick); #line default #line hidden return; case 14: #line 133 "..\..\..\Windows\ElysiumView.xaml" ((System.Windows.Controls.MenuItem)(target)).Click += new System.Windows.RoutedEventHandler(this.AccentClick); #line default #line hidden return; case 15: #line 140 "..\..\..\Windows\ElysiumView.xaml" ((System.Windows.Controls.MenuItem)(target)).Click += new System.Windows.RoutedEventHandler(this.AccentClick); #line default #line hidden return; case 16: #line 147 "..\..\..\Windows\ElysiumView.xaml" ((System.Windows.Controls.MenuItem)(target)).Click += new System.Windows.RoutedEventHandler(this.AccentClick); #line default #line hidden return; case 17: #line 154 "..\..\..\Windows\ElysiumView.xaml" ((System.Windows.Controls.MenuItem)(target)).Click += new System.Windows.RoutedEventHandler(this.AccentClick); #line default #line hidden return; case 18: #line 161 "..\..\..\Windows\ElysiumView.xaml" ((System.Windows.Controls.MenuItem)(target)).Click += new System.Windows.RoutedEventHandler(this.AccentClick); #line default #line hidden return; case 19: this.ContrastGlyph = ((System.Windows.Documents.Glyphs)(target)); #line 173 "..\..\..\Windows\ElysiumView.xaml" this.ContrastGlyph.Initialized += new System.EventHandler(this.ContrastGlyphInitialized); #line default #line hidden return; case 20: #line 182 "..\..\..\Windows\ElysiumView.xaml" ((System.Windows.Controls.MenuItem)(target)).Click += new System.Windows.RoutedEventHandler(this.WhiteClick); #line default #line hidden return; case 21: #line 184 "..\..\..\Windows\ElysiumView.xaml" ((System.Windows.Controls.MenuItem)(target)).Click += new System.Windows.RoutedEventHandler(this.BlackClick); #line default #line hidden return; case 22: #line 189 "..\..\..\Windows\ElysiumView.xaml" ((Elysium.Controls.CommandButton)(target)).Click += new System.Windows.RoutedEventHandler(this.NotificationClick); #line default #line hidden return; case 23: #line 204 "..\..\..\Windows\ElysiumView.xaml" ((System.Windows.Controls.MenuItem)(target)).Click += new System.Windows.RoutedEventHandler(this.AuthorsClick); #line default #line hidden return; case 24: #line 205 "..\..\..\Windows\ElysiumView.xaml" ((System.Windows.Controls.MenuItem)(target)).Click += new System.Windows.RoutedEventHandler(this.LicenseClick); #line default #line hidden return; case 25: #line 206 "..\..\..\Windows\ElysiumView.xaml" ((System.Windows.Controls.MenuItem)(target)).Click += new System.Windows.RoutedEventHandler(this.DonateClick); #line default #line hidden return; } this._contentLoaded = true; }
//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; } }
// Token: 0x06002FD7 RID: 12247 RVA: 0x000D7794 File Offset: 0x000D5994 private int ParseGlyphsProperty(GlyphTypeface fontFace, string unicodeString, bool sideways, out List <Glyphs.ParsedGlyphData> parsedGlyphs, out ushort[] clusterMap) { string indices = this.Indices; int num = 0; int i = 0; int num2 = 1; int num3 = 1; bool flag = false; int num4; if (!string.IsNullOrEmpty(unicodeString)) { clusterMap = new ushort[unicodeString.Length]; num4 = unicodeString.Length; } else { clusterMap = null; num4 = 8; } if (!string.IsNullOrEmpty(indices)) { num4 = Math.Max(num4, indices.Length / 5); } parsedGlyphs = new List <Glyphs.ParsedGlyphData>(num4); Glyphs.ParsedGlyphData parsedGlyphData = new Glyphs.ParsedGlyphData(); if (!string.IsNullOrEmpty(indices)) { int num5 = 0; int num6 = 0; for (int j = 0; j <= indices.Length; j++) { char c = (j < indices.Length) ? indices[j] : '\0'; if (c == ',' || c == ';' || j == indices.Length) { int length = j - num6; string text = indices.Substring(num6, length); switch (num5) { case 0: { bool flag2 = flag; if (!this.ReadGlyphIndex(text, ref flag, ref num3, ref num2, ref parsedGlyphData.glyphIndex)) { if (string.IsNullOrEmpty(unicodeString)) { throw new ArgumentException(SR.Get("GlyphsIndexRequiredIfNoUnicode")); } if (unicodeString.Length <= i) { throw new ArgumentException(SR.Get("GlyphsUnicodeStringIsTooShort")); } parsedGlyphData.glyphIndex = this.GetGlyphFromCharacter(fontFace, unicodeString[i]); } if (!flag2 && clusterMap != null) { if (flag) { for (int k = i; k < i + num2; k++) { Glyphs.SetClusterMapEntry(clusterMap, k, (ushort)num); } } else { Glyphs.SetClusterMapEntry(clusterMap, i, (ushort)num); } } parsedGlyphData.advanceWidth = Glyphs.GetAdvanceWidth(fontFace, parsedGlyphData.glyphIndex, sideways); break; } case 1: if (!Glyphs.IsEmpty(text)) { parsedGlyphData.advanceWidth = double.Parse(text, CultureInfo.InvariantCulture); if (parsedGlyphData.advanceWidth < 0.0) { throw new ArgumentException(SR.Get("GlyphsAdvanceWidthCannotBeNegative")); } } break; case 2: if (!Glyphs.IsEmpty(text)) { parsedGlyphData.offsetX = double.Parse(text, CultureInfo.InvariantCulture); } break; case 3: if (!Glyphs.IsEmpty(text)) { parsedGlyphData.offsetY = double.Parse(text, CultureInfo.InvariantCulture); } break; default: throw new ArgumentException(SR.Get("GlyphsTooManyCommas")); } num5++; num6 = j + 1; } if (c == ';' || j == indices.Length) { parsedGlyphs.Add(parsedGlyphData); parsedGlyphData = new Glyphs.ParsedGlyphData(); if (flag) { num3--; if (num3 == 0) { i += num2; flag = false; } } else { i++; } num++; num5 = 0; num6 = j + 1; } } } if (unicodeString != null) { while (i < unicodeString.Length) { if (flag) { throw new ArgumentException(SR.Get("GlyphsIndexRequiredWithinCluster")); } if (unicodeString.Length <= i) { throw new ArgumentException(SR.Get("GlyphsUnicodeStringIsTooShort")); } parsedGlyphData.glyphIndex = this.GetGlyphFromCharacter(fontFace, unicodeString[i]); parsedGlyphData.advanceWidth = Glyphs.GetAdvanceWidth(fontFace, parsedGlyphData.glyphIndex, sideways); parsedGlyphs.Add(parsedGlyphData); parsedGlyphData = new Glyphs.ParsedGlyphData(); Glyphs.SetClusterMapEntry(clusterMap, i, (ushort)num); i++; num++; } } return(num); }
private ITextPointer _SnapToText(Point point) { ITextPointer itp = null; FixedNode[] fixedNodes = Container.FixedTextBuilder.GetLine(this.PageIndex, point); if (fixedNodes != null && fixedNodes.Length > 0) { double closestDistance = Double.MaxValue; double xoffset = 0; Glyphs closestGlyphs = null; FixedNode closestNode = fixedNodes[0]; foreach (FixedNode node in fixedNodes) { Glyphs startGlyphs = this.FixedPage.GetGlyphsElement(node); GeneralTransform tranToGlyphs = this.FixedPage.TransformToDescendant(startGlyphs); Point transformedPt = point; if (tranToGlyphs != null) { tranToGlyphs.TryTransform(transformedPt, out transformedPt); } GlyphRun run = startGlyphs.ToGlyphRun(); Rect alignmentRect = run.ComputeAlignmentBox(); alignmentRect.Offset(startGlyphs.OriginX, startGlyphs.OriginY); double horizontalDistance = Math.Max(0, (transformedPt.X > alignmentRect.X) ? (transformedPt.X - alignmentRect.Right) : (alignmentRect.X - transformedPt.X)); double verticalDistance = Math.Max(0, (transformedPt.Y > alignmentRect.Y) ? (transformedPt.Y - alignmentRect.Bottom) : (alignmentRect.Y - transformedPt.Y)); double manhattanDistance = horizontalDistance + verticalDistance; if (closestGlyphs == null || manhattanDistance < closestDistance) { closestDistance = manhattanDistance; closestGlyphs = startGlyphs; closestNode = node; xoffset = transformedPt.X; } } int index; LogicalDirection dir; _GlyphRunHitTest(closestGlyphs, xoffset, out index, out dir); FixedPosition fixedp = new FixedPosition(closestNode, index); itp = _CreateTextPointer(fixedp, dir); Debug.Assert(itp != null); } else { // // That condition is only possible when there is no line in the page // if (point.Y < this.FixedPage.Height / 2) { itp = ((ITextPointer)this.Start).CreatePointer(LogicalDirection.Forward); itp.MoveToInsertionPosition(LogicalDirection.Forward); } else { itp = ((ITextPointer)this.End).CreatePointer(LogicalDirection.Backward); itp.MoveToInsertionPosition(LogicalDirection.Backward); } } return(itp); }
// If return false, nothing has been modified, which implies out of page boundary // The input of suggestedX is in the VisualRoot's cooridnate system private bool _GetNextLineGlyphs(ref FixedPosition fixedp, ref LogicalDirection edge, double suggestedX, LogicalDirection scanDir) { int count = 1; int pageIndex = fixedp.Page; bool moved = false; FixedNode[] fixedNodes = Container.FixedTextBuilder.GetNextLine(fixedp.Node, (scanDir == LogicalDirection.Forward), ref count); if (fixedNodes != null && fixedNodes.Length > 0) { FixedPage page = Container.FixedDocument.SyncGetPage(pageIndex, false); // This line contains multiple Glyhs. Scan backward // util we hit the first one whose OriginX is smaller // then suggestedX; if (Double.IsInfinity(suggestedX)) { suggestedX = 0; } Point topOfPage = new Point(suggestedX, 0); Point secondPoint = new Point(suggestedX, 1000); FixedNode hitNode = fixedNodes[0]; Glyphs hitGlyphs = null; double closestDistance = Double.MaxValue; double xoffset = 0; for (int i = fixedNodes.Length - 1; i >= 0; i--) { FixedNode node = fixedNodes[i]; Glyphs g = page.GetGlyphsElement(node); if (g != null) { GeneralTransform transform = page.TransformToDescendant(g); Point pt1 = topOfPage; Point pt2 = secondPoint; if (transform != null) { transform.TryTransform(pt1, out pt1); transform.TryTransform(pt2, out pt2); } double invSlope = (pt2.X - pt1.X) / (pt2.Y - pt1.Y); double xoff, distance; GlyphRun run = g.ToGlyphRun(); Rect box = run.ComputeAlignmentBox(); box.Offset(g.OriginX, g.OriginY); if (invSlope > 1000 || invSlope < -1000) { // special case for vertical text xoff = 0; distance = (pt1.Y > box.Y) ? (pt1.Y - box.Bottom) : (box.Y - pt1.Y); } else { double centerY = (box.Top + box.Bottom) / 2; xoff = pt1.X + invSlope * (centerY - pt1.Y); distance = (xoff > box.X) ? (xoff - box.Right) : (box.X - xoff); } if (distance < closestDistance) { closestDistance = distance; xoffset = xoff; hitNode = node; hitGlyphs = g; if (distance <= 0) { break; } } } } Debug.Assert(hitGlyphs != null); int charIdx; _GlyphRunHitTest(hitGlyphs, xoffset, out charIdx, out edge); fixedp = new FixedPosition(hitNode, charIdx); moved = true; } return(moved); }
//gets text within selected area private string GetText() { double top = _selectionRect.Top; double bottom = _selectionRect.Bottom; double left = _selectionRect.Left; double right = _selectionRect.Right; double lastBaseline = 0; double baseline = 0; double lastHeight = 0; double height = 0; int nChildren = _page.Children.Count; ArrayList ranges = new ArrayList(); //text ranges in area FixedNode[] nodesInLine = _panel.FixedContainer.FixedTextBuilder.GetFirstLine(_pageIndex); while (nodesInLine != null && nodesInLine.Length > 0) { TextPositionPair textRange = null; //current text range foreach (FixedNode node in nodesInLine) { Glyphs g = _page.GetGlyphsElement(node); if (g != null) { int begin, end; //first and last index in range bool includeEnd; //is the end of this glyphs included in selection? if (IntersectGlyphs(g, top, left, bottom, right, out begin, out end, out includeEnd, out baseline, out height)) { if (textRange == null || begin > 0) { //begin new text range textRange = new TextPositionPair(); textRange.first = _GetTextPosition(node, begin); ranges.Add(textRange); } textRange.second = _GetTextPosition(node, end); if (!includeEnd) { // so future textRanges aren't concatenated with this one textRange = null; } } else { //this Glyphs completely outside selected region textRange = null; } lastBaseline = baseline; lastHeight = height; } } int count = 1; nodesInLine = _panel.FixedContainer.FixedTextBuilder.GetNextLine(nodesInLine[0], true, ref count); } string text = ""; foreach (TextPositionPair range in ranges) { Debug.Assert(range.first != null && range.second != null); text = text + TextRangeBase.GetTextInternal(range.first, range.second) + "\r\n"; //CRLF } return(text); }