public static MathListIndex IndexForPoint <TFont, TGlyph>(this FractionDisplay <TFont, TGlyph> self, TypesettingContext <TFont, TGlyph> context, PointF point) where TFont : IFont <TGlyph> { // We can be before or after the fraction if (point.X < self.Position.X - PixelDelta) { //We are before the fraction, so return(MathListIndex.Level0Index(self.Range.Location)); } else if (point.X > self.Position.X + self.Width + PixelDelta) { //We are after the fraction return(MathListIndex.Level0Index(self.Range.End)); } if (point.Y > self.LinePosition + PixelDelta) { return(MathListIndex.IndexAtLocation(self.Range.Location, MathListSubIndexType.Numerator, self.Numerator.IndexForPoint(context, point))); } else if (point.Y < self.LinePosition - PixelDelta) { return(MathListIndex.IndexAtLocation(self.Range.Location, MathListSubIndexType.Denominator, self.Denominator.IndexForPoint(context, point))); } if (point.X > self.Position.X + self.Width / 2) { return(MathListIndex.Level0Index(self.Range.End)); } return(MathListIndex.Level0Index(self.Range.Location)); }
public static MathListIndex IndexForPoint <TFont, TGlyph>(this RadicalDisplay <TFont, TGlyph> self, TypesettingContext <TFont, TGlyph> context, PointF point) where TFont : IFont <TGlyph> { // We can be before or after the radical if (point.X < self.Position.X - PixelDelta) { //We are before the radical, so return(MathListIndex.Level0Index(self.Range.Location)); } else if (point.X > self.Position.X + self.Width + PixelDelta) { //We are after the radical return(MathListIndex.Level0Index(self.Range.End)); } //We can be either near the degree or the radicand var degreeRect = self.Degree != null ? new RectangleF(self.Degree.Position, self.Degree.DisplayBounds.Size) : default; var radicandRect = new RectangleF(self.Radicand.Position, self.Radicand.DisplayBounds.Size); var degreeDistance = DistanceFromPointToRect(point, degreeRect); var radicandDistance = DistanceFromPointToRect(point, radicandRect); if (degreeDistance < radicandDistance) { if (self.Degree != null) { return(MathListIndex.IndexAtLocation(self.Range.Location, MathListSubIndexType.Degree, self.Degree.IndexForPoint(context, point))); } return(MathListIndex.Level0Index(self.Range.Location)); } else { return(MathListIndex.IndexAtLocation(self.Range.Location, MathListSubIndexType.Radicand, self.Radicand.IndexForPoint(context, point))); } }
public static MathListIndex IndexForPoint <TFont, TGlyph>(this FractionDisplay <TFont, TGlyph> self, TypesettingContext <TFont, TGlyph> context, PointF point) where TFont : IFont <TGlyph> { // We can be before or after the fraction if (point.X < self.Position.X - PixelDelta) { //We are before the fraction, so return(MathListIndex.Level0Index(self.Range.Location)); } else if (point.X > self.Position.X + self.Width + PixelDelta) { //We are after the fraction return(MathListIndex.Level0Index(self.Range.End)); } //We can be either near the numerator or denominator var numeratorDistance = DistanceFromPointToRect(point, self.Numerator.DisplayBounds); var denominatorDistance = DistanceFromPointToRect(point, self.Denominator.DisplayBounds); if (numeratorDistance < denominatorDistance) { return(MathListIndex.IndexAtLocation(self.Range.Location, self.Numerator.IndexForPoint(context, point), MathListSubIndexType.Numerator)); } else { return(MathListIndex.IndexAtLocation(self.Range.Location, self.Denominator.IndexForPoint(context, point), MathListSubIndexType.Denominator)); } }
public static MathListIndex IndexForPoint <TFont, TGlyph>(this RadicalDisplay <TFont, TGlyph> self, TypesettingContext <TFont, TGlyph> context, PointF point) where TFont : IFont <TGlyph> { // We can be before or after the radical if (point.X < self.Position.X - PixelDelta) { //We are before the radical, so return(MathListIndex.Level0Index(self.Range.Location)); } else if (point.X > self.Position.X + self.Width + PixelDelta) { //We are after the radical return(MathListIndex.Level0Index(self.Range.End)); } //We can be either near the degree or the radicand var degreeDistance = DistanceFromPointToRect(point, self.Degree?.DisplayBounds ?? default); var radicandDistance = DistanceFromPointToRect(point, self.Radicand.DisplayBounds); if (degreeDistance < radicandDistance) { return(MathListIndex.IndexAtLocation(self.Range.Location, self.Degree.IndexForPoint(context, point), MathListSubIndexType.Numerator)); } else { return(MathListIndex.IndexAtLocation(self.Range.Location, self.Radicand.IndexForPoint(context, point), MathListSubIndexType.Denominator)); } }
public static MathListIndex IndexForPoint <TFont, TGlyph>( this InnerDisplay <TFont, TGlyph> self, TypesettingContext <TFont, TGlyph> context, PointF point) where TFont : IFont <TGlyph> => // We can be before or after the inner point.X <self.Position.X + (self.Left?.Width / 2 ?? 0) //We are before the inner, so ? MathListIndex.Level0Index(self.Range.Location) : point.X> self.Position.X + self.Width - (self.Right?.Width / 2 ?? 0) //We are after the inner ? MathListIndex.Level0Index(self.Range.End) : MathListIndex.IndexAtLocation(self.Range.Location, MathListSubIndexType.Inner, self.Inner.IndexForPoint(context, point));
public static MathListIndex IndexForPoint <TFont, TGlyph>( this RadicalDisplay <TFont, TGlyph> self, TypesettingContext <TFont, TGlyph> context, PointF point) where TFont : IFont <TGlyph> => // We can be before or after the radical point.X <self.Position.X - PixelDelta //We are before the radical, so ?MathListIndex.Level0Index(self.Range.Location) : point.X> self.Position.X + self.Width + PixelDelta //We are after the radical ? MathListIndex.Level0Index(self.Range.End) //We can be either near the degree or the radicand : DistanceFromPointToRect(point, self.Degree != null ? new RectangleF(self.Degree.Position, self.Degree.DisplayBounds().Size) : default) < DistanceFromPointToRect(point, new RectangleF(self.Radicand.Position, self.Radicand.DisplayBounds().Size)) ? self.Degree != null ? MathListIndex.IndexAtLocation(self.Range.Location, MathListSubIndexType.Degree, self.Degree.IndexForPoint(context, point)) : MathListIndex.Level0Index(self.Range.Location) : MathListIndex.IndexAtLocation(self.Range.Location, MathListSubIndexType.Radicand, self.Radicand.IndexForPoint(context, point));
public static MathListIndex IndexForPoint <TFont, TGlyph>(this ListDisplay <TFont, TGlyph> self, TypesettingContext <TFont, TGlyph> context, PointF point) where TFont : IFont <TGlyph> { // The origin of for the subelements of a MathList is the current position, so translate the current point to our origin. var translatedPoint = new PointF(point.X - self.Position.X, point.Y - self.Position.Y); IDisplay <TFont, TGlyph> closest = null; var xbounds = new List <IDisplay <TFont, TGlyph> >(); float minDistance = float.MaxValue; foreach (var display in self.Displays) { var bounds = display.DisplayBounds; var rect = new RectangleF(display.Position, bounds.Size); var maxBoundsX = rect.Right; if (rect.X - PixelDelta <= translatedPoint.X && translatedPoint.X <= maxBoundsX + PixelDelta) { xbounds.Add(display); } var distance = DistanceFromPointToRect(translatedPoint, rect); if (distance < minDistance) { closest = display; minDistance = distance; } } IDisplay <TFont, TGlyph> displayWithPoint; switch (xbounds.Count) { case 0: if (translatedPoint.X <= -PixelDelta) { // All the way to the left return(self.Range.Location < 0 ? null : MathListIndex.Level0Index(self.Range.Location)); } else if (translatedPoint.X >= self.Width + PixelDelta) { // if closest is a script if (closest != null && closest is ListDisplay <TFont, TGlyph> ld && ld.LinePosition != Enumerations.LinePosition.Regular) { // then we try to find its parent var parent = self.Displays.FirstOrDefault(d => d.HasScript && d.Range.Contains(ld.IndexInParent)); if (parent != null) { return(MathListIndex.Level0Index(parent.Range.End)); } } // All the way to the right return(self.Range.End < 0 ? null : MathListIndex.Level0Index(self.Range.End)); } else { // It is within the ListDisplay but not within the X bounds of any sublist. Use the closest in that case. displayWithPoint = closest; } break; case 1: displayWithPoint = xbounds[0]; var rect = new RectangleF(displayWithPoint.Position, displayWithPoint.DisplayBounds.Size); if (translatedPoint.X >= self.Width - PixelDelta) { //The point is close to the end. Only use the selected X bounds if the Y is within range. if (translatedPoint.Y <= rect.YMin() - PixelDelta) { //The point is less than the Y including the delta. Move the cursor to the end rather than in this atom. return(MathListIndex.Level0Index(self.Range.End)); } } break; default: //Use the closest since there are more than 2 sublists which have this X position. displayWithPoint = closest; break; } if (displayWithPoint is null) { return(null); } var index = displayWithPoint.IndexForPoint(context, translatedPoint); if (displayWithPoint is ListDisplay <TFont, TGlyph> closestLine) { if (closestLine.LinePosition is Enumerations.LinePosition.Regular) { throw Arg($"{nameof(ListDisplay<TFont, TGlyph>)} {nameof(ListDisplay<TFont, TGlyph>.LinePosition)} {nameof(Enumerations.LinePosition.Regular)} " + $"inside an {nameof(ListDisplay<TFont, TGlyph>)} - shouldn't happen", nameof(self)); } // This is a subscript or a superscript, return the right type of subindex var indexType = closestLine.LinePosition is Enumerations.LinePosition.Subscript ? MathListSubIndexType.Subscript : MathListSubIndexType.Superscript; // The index of the atom this denotes. if (closestLine.IndexInParent is int.MinValue) { throw Arg($"Index was not set for a {indexType} in the {nameof(ListDisplay<TFont, TGlyph>)}.", nameof(self)); } return(MathListIndex.IndexAtLocation(closestLine.IndexInParent, indexType, index)); } else if (displayWithPoint.HasScript) { //The display list has a subscript or a superscript. If the index is at the end of the atom, then we need to put it before the sub/super script rather than after. if (index?.AtomIndex == displayWithPoint.Range.End) { return(MathListIndex.IndexAtLocation(index.AtomIndex - 1, MathListSubIndexType.BetweenBaseAndScripts, MathListIndex.Level0Index(1))); } } return(index); }