// Helper for UpdateCaretState -- calculates caret rectangle from text selection. // regular (non-interim) case of caret positioning private static Rect CalculateCaretRectangle(ITextSelection currentTextSelection, ITextPointer caretPosition) { Transform caretTransform; Rect caretRectangle = currentTextSelection.TextView.GetRawRectangleFromTextPosition(caretPosition, out caretTransform); if (caretRectangle.IsEmpty) { // Caret is not at an insertion position, it has no geometry // and will not be displayed. return Rect.Empty; } // Convert to local coordiantes. caretRectangle = caretTransform.TransformBounds(caretRectangle); // We will use the system defined caret width later. caretRectangle.Width = 0; if (currentTextSelection.IsEmpty) { // Calculate caret height - from current font size (ignoring a rect returned by TextView, // as it can be a rect of embedded object, which should not affect caret height) double fontSize = (double)currentTextSelection.GetPropertyValue(TextElement.FontSizeProperty); FontFamily fontFamily = (FontFamily)currentTextSelection.GetPropertyValue(TextElement.FontFamilyProperty); double caretHeight = fontFamily.LineSpacing * fontSize; if (caretHeight < caretRectangle.Height) { // Decrease the height of caret to the font height and lower the caret to keep its bottom // staying on the baseline. caretRectangle.Y += caretRectangle.Height - caretHeight; caretRectangle.Height = caretHeight; } if (!caretTransform.IsIdentity) { Point top = new Point(caretRectangle.X, caretRectangle.Y); Point bottom = new Point(caretRectangle.X, caretRectangle.Y + caretRectangle.Height); caretTransform.TryTransform(top, out top); caretTransform.TryTransform(bottom, out bottom); caretRectangle.Y += caretRectangle.Height - Math.Abs(bottom.Y - top.Y); caretRectangle.Height = Math.Abs(bottom.Y - top.Y); } } return caretRectangle; }