private Rect GetBounds(StylusPoint stylusPoint, Point position, IInputElement relativeTo, GeneralTransform elementToRoot, GeneralTransform rootToElement) { // Get width and heith in pixel value double width = GetStylusPointWidthOrHeight(stylusPoint, /*isWidth*/ true); double height = GetStylusPointWidthOrHeight(stylusPoint, /*isWidth*/ false); // Get the position with respect to root Point rootPoint; if (elementToRoot == null || !elementToRoot.TryTransform(position, out rootPoint)) { rootPoint = position; } // Create a Rect with respect to root and transform it to element coordinate space Rect rectBounds = new Rect(rootPoint.X - width * 0.5, rootPoint.Y - height * 0.5, width, height); if (rootToElement != null) { rectBounds = rootToElement.TransformBounds(rectBounds); } return rectBounds; }
// Creates an axis-aligned caret for possibly rotated glyphs private Rect _GetTransformedCaretRect(GeneralTransform transform, Point origin, double height) { Point bottom = origin; bottom.Y += height; transform.TryTransform(origin, out origin); transform.TryTransform(bottom, out bottom); Rect caretRect = new Rect(origin, bottom); if (caretRect.Width > 0) { // only vertical carets are supported by TextEditor // What to do if height == 0? caretRect.X += caretRect.Width / 2; caretRect.Width = 0; } if (caretRect.Height < 1) { caretRect.Height = 1; } return caretRect; }
// Clips a Point to the ActualWidth/Height of a containing FrameworkElement. private static void ClipToElement(FrameworkElement element, GeneralTransform transform, ref double horizontalOffset, ref double verticalOffset) { Point minPoint; Point maxPoint; Geometry clip = VisualTreeHelper.GetClip(element); if (clip != null) { Rect bounds = clip.Bounds; minPoint = new Point(bounds.X, bounds.Y); maxPoint = new Point(bounds.X + bounds.Width, bounds.Y + bounds.Height); } else { if (element.ActualWidth == 0 && element.ActualHeight == 0) { // Some elements, noteably Canvas, have a (0, 0) desired size // and should be ignored. return; } minPoint = new Point(0, 0); maxPoint = new Point(element.ActualWidth, element.ActualHeight); } transform.TryTransform(minPoint, out minPoint); transform.TryTransform(maxPoint, out maxPoint); // NB: ClipToBounds will handle the case where transform flips a coordinate // axis. In that case, minPoint.X will be > maxPoint.X. horizontalOffset = ClipToBounds(minPoint.X, horizontalOffset, maxPoint.X); verticalOffset = ClipToBounds(minPoint.Y, verticalOffset, maxPoint.Y); }