|
|
|
@ -1,5 +1,6 @@ |
|
|
|
using System; |
|
|
|
using System.Buffers; |
|
|
|
using System.Collections.Concurrent; |
|
|
|
using System.Globalization; |
|
|
|
using System.Runtime.InteropServices; |
|
|
|
using Avalonia.Media.TextFormatting; |
|
|
|
@ -13,6 +14,8 @@ namespace Avalonia.Direct2D1.Media |
|
|
|
{ |
|
|
|
internal class TextShaperImpl : ITextShaperImpl |
|
|
|
{ |
|
|
|
private static readonly ConcurrentDictionary<int, Language> s_cachedLanguage = new(); |
|
|
|
|
|
|
|
public ShapedBuffer ShapeText(ReadOnlyMemory<char> text, TextShaperOptions options) |
|
|
|
{ |
|
|
|
var textSpan = text.Span; |
|
|
|
@ -24,8 +27,8 @@ namespace Avalonia.Direct2D1.Media |
|
|
|
using (var buffer = new Buffer()) |
|
|
|
{ |
|
|
|
// HarfBuzz needs the surrounding characters to correctly shape the text
|
|
|
|
var containingText = GetContainingMemory(text, out var start, out var length); |
|
|
|
buffer.AddUtf16(containingText.Span, start, length); |
|
|
|
var containingText = GetContainingMemory(text, out var start, out var length).Span; |
|
|
|
buffer.AddUtf16(containingText, start, length); |
|
|
|
|
|
|
|
MergeBreakPair(buffer); |
|
|
|
|
|
|
|
@ -33,7 +36,9 @@ namespace Avalonia.Direct2D1.Media |
|
|
|
|
|
|
|
buffer.Direction = (bidiLevel & 1) == 0 ? Direction.LeftToRight : Direction.RightToLeft; |
|
|
|
|
|
|
|
buffer.Language = new Language(culture ?? CultureInfo.CurrentCulture); |
|
|
|
var usedCulture = culture ?? CultureInfo.CurrentCulture; |
|
|
|
|
|
|
|
buffer.Language = s_cachedLanguage.GetOrAdd(usedCulture.LCID, _ => new Language(usedCulture)); |
|
|
|
|
|
|
|
var font = ((GlyphTypefaceImpl)typeface).Font; |
|
|
|
|
|
|
|
@ -68,7 +73,7 @@ namespace Avalonia.Direct2D1.Media |
|
|
|
|
|
|
|
var glyphOffset = GetGlyphOffset(glyphPositions, i, textScale); |
|
|
|
|
|
|
|
if (i < textSpan.Length && textSpan[i] == '\t') |
|
|
|
if (glyphCluster < containingText.Length && containingText[glyphCluster] == '\t') |
|
|
|
{ |
|
|
|
glyphIndex = typeface.GetGlyph(' '); |
|
|
|
|
|
|
|
|