Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CSharpMath.Apple/Drawing/AppleGraphicsContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
using CoreText;
using CSharpMath.Display.Text;
using CSharpMath.FrontEnd;
using CSharpMath.Structures;
using Color = CSharpMath.Structures.Color;
using UIKit;
using TFont = CSharpMath.Apple.AppleMathFont;
using TGlyph = System.UInt16;
Expand Down
18 changes: 11 additions & 7 deletions CSharpMath.Editor/Extensions/DisplayEditingExtensions.Fraction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,24 @@ public static MathListIndex IndexForPoint<TFont, TGlyph>(this FractionDisplay<TF
//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)
if (point.Y > self.LinePosition + PixelDelta)
return MathListIndex.IndexAtLocation(self.Range.Location, self.Numerator.IndexForPoint(context, point), MathListSubIndexType.Numerator);
else
else if (point.Y < self.LinePosition - PixelDelta)
return MathListIndex.IndexAtLocation(self.Range.Location, self.Denominator.IndexForPoint(context, point), MathListSubIndexType.Denominator);
if (point.X > self.Position.X + self.Width / 2)
return MathListIndex.Level0Index(self.Range.End);

return MathListIndex.Level0Index(self.Range.Location);
}

public static PointF? PointForIndex<TFont, TGlyph>(this FractionDisplay<TFont, TGlyph> self, TypesettingContext<TFont, TGlyph> context, MathListIndex index) where TFont : IFont<TGlyph> {
if (index.SubIndexType != MathListSubIndexType.None)
throw Arg("The subindex must be none to get the closest point for it.", nameof(index));
// draw a caret after the fraction
return new PointF(self.DisplayBounds.Right, self.Position.Y);
if (index.AtomIndex == self.Range.End)
// draw a caret after the fraction
return new PointF(self.DisplayBounds.Right, self.Position.Y);
// draw a caret before the fraction
return new PointF(self.DisplayBounds.Left, self.Position.Y);
}

public static void HighlightCharacterAt<TFont, TGlyph>(this FractionDisplay<TFont, TGlyph> self, MathListIndex index, Color color) where TFont : IFont<TGlyph> {
Expand Down
36 changes: 27 additions & 9 deletions CSharpMath.Editor/Extensions/DisplayEditingExtensions.List.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ namespace CSharpMath.Editor {
using System;
using System.Collections.Generic;
using System.Drawing;

using System.Linq;
using Display;
using Display.Text;
using FrontEnd;
Expand All @@ -18,10 +18,11 @@ public static MathListIndex IndexForPoint<TFont, TGlyph>(this ListDisplay<TFont,
float minDistance = float.MaxValue;
foreach (var display in self.Displays) {
var bounds = display.DisplayBounds;
var maxBoundsX = bounds.Right;
if (bounds.X - PixelDelta <= translatedPoint.X && translatedPoint.X <= maxBoundsX + PixelDelta)
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, bounds);
var distance = DistanceFromPointToRect(translatedPoint, rect);
if (distance < minDistance) {
closest = display;
minDistance = distance;
Expand All @@ -33,18 +34,23 @@ public static MathListIndex IndexForPoint<TFont, TGlyph>(this ListDisplay<TFont,
if (translatedPoint.X <= -PixelDelta)
// All the way to the left
return MathListIndex.Level0Index(self.Range.Location);
else if (translatedPoint.X >= self.Width + PixelDelta)
else if (translatedPoint.X >= self.Width + PixelDelta) {
// All the way to the right
if (closest != null) {
return MathListIndex.Level0Index(closest.Range.End);
}
// All the way to the right
return MathListIndex.Level0Index(self.Range.End);
else
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 <= displayWithPoint.DisplayBounds.YMin() - PixelDelta)
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;
Expand Down Expand Up @@ -88,7 +94,19 @@ public static MathListIndex IndexForPoint<TFont, TGlyph>(this ListDisplay<TFont,
position = display.PointForIndex(context, MathListIndex.Level0Index(nucleusPosition));
break;
case MathListSubIndexType.None:
position = display.PointForIndex(context, index);
if (!display.HasScript) {
position = display.PointForIndex(context, index);
} else {
var mainPosition = display.PointForIndex(context, index);
var scripted = self.Displays.SingleOrDefault(d =>
d is ListDisplay<TFont, TGlyph> ld &&
ld.IndexInParent == index.AtomIndex - 1
);
if (scripted != null && mainPosition != null) {
position = new PointF(mainPosition.Value.X + scripted.Width, 0);
} else
position = mainPosition;
}
break;
default:
// Recurse
Expand Down
28 changes: 14 additions & 14 deletions CSharpMath.Editor/Extensions/DisplayEditingExtensions.TextLine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,23 @@ namespace CSharpMath.Editor {

public partial class DisplayEditingExtensions {
public static int? GlyphIndexForXOffset<TFont, TGlyph>(this AttributedGlyphRun<TFont, TGlyph> line, TypesettingContext<TFont, TGlyph> context, float offset) where TFont : IFont<TGlyph> {
if (offset < 0) return 0; //Move cursor to index 0
if (offset < 0) return 0; // Move cursor to index 0
if (line.Placeholder) return 0;
int i = 0;
float x = 0;
var advances = context.GlyphBoundsProvider.GetAdvancesForGlyphs(line.Font, line.Glyphs.AsForEach(), line.Length).Advances;
foreach (var (advance, kernAfter) in advances.Zip(line.GlyphInfos.Select(g => g.KernAfterGlyph), ValueTuple.Create))
if (x <= offset && offset < advance + x)
return i;
else {
if (x <= offset && offset < advance + x) {
if (Math.Abs(offset - x) < Math.Abs(advance + x - offset))
return i;
return i + 1;
} else {
x += advance + kernAfter;
i++;
if (offset < x) //If the point is in the kern after this, then the index is the one after this
if (offset < x) // If the point is in the kern after this, then the index is the one after this
return i;
}
return null;
return i;
}

public static float XOffsetForGlyphIndex<TFont, TGlyph>(this AttributedGlyphRun<TFont, TGlyph> line, TypesettingContext<TFont, TGlyph> context, int index) where TFont : IFont<TGlyph> {
Expand Down Expand Up @@ -67,19 +70,16 @@ public static int MathListIndexToStringIndex<TFont, TGlyph>(this TextLineDisplay
public static MathListIndex IndexForPoint<TFont, TGlyph>(this TextLineDisplay<TFont, TGlyph> self, TypesettingContext<TFont, TGlyph> context, PointF point) where TFont : IFont<TGlyph> {
// Convert the point to the reference of the CTLine
var relativePoint = new PointF(point.X - self.Position.X, point.Y - self.Position.Y);
var indices = self.Runs.Select(run => run.Run.GlyphIndexForXOffset(context, relativePoint.Plus(run.Position).X)).Where(x => x.HasValue);
if (indices.IsEmpty())
var indices = self.Runs.Select(run => run.Run.GlyphIndexForXOffset(context, relativePoint.Plus(run.Position).X)).Where(x => x.HasValue).ToArray();
if (indices.Length == 0)
return null;
var index = indices.Single().GetValueOrDefault();
// The index returned is in UTF-16, translate to codepoint index.
// NSUInteger codePointIndex = stringIndexToCodePointIndex(self.attributedString.string, index);
// Convert the code point index to an index into the mathlist
var mlIndex = self.StringIndexToMathListIndex(index);

// index will be between 0 and _range.length inclusive
if (mlIndex < 0 || mlIndex > self.Range.Length)
if (index < 0 || index > self.Range.Length)
throw new InvalidCodePathException($"Returned index out of range: {index}, range ({self.Range.Location}, {self.Range.Length})");
// translate to the current index
return MathListIndex.Level0Index(self.Range.Location + mlIndex);
return MathListIndex.Level0Index(self.Range.Location + index);
}

public static (TextRunDisplay<TFont, TGlyph> run, int charIndex) GetRunAndCharIndexFromStringIndex<TFont, TGlyph>(this TextLineDisplay<TFont, TGlyph> self, int lineCharIndex) where TFont : IFont<TGlyph> {
Expand Down
3 changes: 2 additions & 1 deletion CSharpMath.Editor/Extensions/DisplayEditingExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ public static float DistanceFromPointToRect(PointF point, RectangleF rect) {
distance += point.Y - rect.YMax();
return distance;
}

public static float DistanceBetweenY(PointF p1, PointF p2) => (p1.Y - p2.Y) * (p1.Y - p2.Y);

/// <summary>
/// Finds the index in the mathlist before which a new character should be inserted.Returns null if it cannot find the index.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,4 @@
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="CSharpMath.Forms.Example.EditorPage"
Title="Editor">
<ContentPage.Content>
<StackLayout>
<Label Text="Welcome to Xamarin.Forms!"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,43 @@
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using CSharpMath.Editor;
using SkiaSharp.Views.Forms;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace CSharpMath.Forms.Example {
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class EditorPage : ContentPage {

public EditorPage() {
InitializeComponent();
var view = new global::SkiaSharp.Views.Forms.SKCanvasView { WidthRequest = 320, HeightRequest = 225 };
this.Content = new EditorView();
}

}

public class EditorView : ContentView {
private MathKeyboard keyboard;

public EditorView() {
keyboard = new MathKeyboard();

var view = new SKCanvasView { WidthRequest = 320, HeightRequest = 225, EnableTouchEvents = true };
view.Touch +=
(sender, e) => {
if (e.ActionType == SKTouchAction.Pressed) {
keyboard.Tap(new System.Drawing.PointF(e.Location.X, e.Location.Y));
}
};

var painter = new SkiaSharp.MathPainter { TextColor = global::SkiaSharp.SKColors.Black };
var keyboard = new MathKeyboard();
keyboard.RedrawRequested += (_, __) => view.InvalidateSurface();
view.PaintSurface +=
(sender, e) => {
e.Surface.Canvas.Clear();
SkiaSharp.MathPainter.DrawDisplay(painter, keyboard.Display, e.Surface.Canvas);
keyboard.DrawCaret(e.Surface.Canvas, Rendering.CaretShape.UpArrow);
keyboard.DrawCaret(e.Surface.Canvas, Rendering.CaretShape.IBeam);
};
Content = new StackLayout { Children = { view, keyboard } };
}
Expand Down
6 changes: 5 additions & 1 deletion CSharpMath.Forms/MathKeyboard.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,17 @@
using Xamarin.Forms.Xaml;

namespace CSharpMath.Forms {
using CSharpMath.Editor;
using Rendering;
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class MathKeyboard : ContentView {
public MathKeyboard() {
InitializeComponent();
}


public void Tap(System.Drawing.PointF point) => Keyboard.Tap(point);

public void DrawCaret(global::SkiaSharp.SKCanvas canvas, CaretShape shape = CaretShape.UpArrow) =>
Keyboard.DrawCaret(new SkiaSharp.SkiaCanvas(canvas, global::SkiaSharp.SKStrokeCap.Butt, false), shape);
public event EventHandler RedrawRequested {
Expand All @@ -30,7 +34,7 @@ public event EventHandler DismissPressed {
remove => Keyboard.DismissPressed -= value;
}

public IDisplay<Rendering.Fonts, Rendering.Glyph> Display => Keyboard.Display;
public IDisplay<Fonts, Glyph> Display => Keyboard.Display;

private void SwitchTab(Grid tab) {
tab.IsVisible = true;
Expand Down
4 changes: 2 additions & 2 deletions CSharpMath/CSharpMath.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.1</TargetFramework>
<LangVersion>latest</LangVersion>
Expand Down Expand Up @@ -38,7 +38,7 @@
<ItemGroup>
<PackageReference Include="System.Buffers" Version="4.5.0" />
<PackageReference Include="System.Memory" Version="4.5.1" />
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.5.2" />
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.5.1" />
</ItemGroup>
<Import Project="..\packages\NuGet.Build.Packaging.0.2.2\build\NuGet.Build.Packaging.targets" Condition="Exists('..\packages\NuGet.Build.Packaging.0.2.2\build\NuGet.Build.Packaging.targets') And '$(Configuration)' == 'Release-iOS'" />
</Project>