@ -12,8 +12,6 @@ using Avalonia.OpenGL.Imaging;
using Avalonia.Platform ;
using Avalonia.Media.Imaging ;
using SkiaSharp ;
using System.Runtime.InteropServices ;
using System.Drawing ;
namespace Avalonia.Skia
{
@ -79,7 +77,7 @@ namespace Avalonia.Skia
var skFont = new SKFont ( glyphTypeface . Typeface , fontRenderingEmSize )
{
Size = fontRenderingEmSize ,
Edging = SKFontEdging . Antia lias ,
Edging = SKFontEdging . Alias ,
Hinting = SKFontHinting . None ,
LinearMetrics = true
} ;
@ -244,85 +242,91 @@ namespace Avalonia.Skia
"Current GPU acceleration backend does not support OpenGL integration" ) ;
}
public IGlyphRunBuffer AllocateGlyphRun ( IGlyphTypeface glyphTypeface , float fontRenderingEmSize , int length )
= > new SKGlyphRunBuffer ( glyphTypeface , fontRenderingEmSize , length ) ;
public IGlyphRunImpl CreateGlyphRun ( IGlyphTypeface glyphTypeface , double fontRenderingEmSize , IReadOnlyList < ushort > glyphIndices ,
IReadOnlyList < double > glyphAdvances , IReadOnlyList < Vector > glyphOffsets )
{
if ( glyphTypeface = = null )
{
throw new ArgumentNullException ( nameof ( glyphTypeface ) ) ;
}
public IHorizontalGlyphRunBuffer AllocateHorizontalGlyphRun ( IGlyphTypeface glyphTypeface , float fontRenderingEmSize , int length )
= > new SKHorizontalGlyphRunBuffer ( glyphTypeface , fontRenderingEmSize , length ) ;
if ( glyphIndices = = null )
{
throw new ArgumentNullException ( nameof ( glyphIndices ) ) ;
}
public IPositionedGlyphRunBuffer AllocatePositionedGlyphRun ( IGlyphTypeface glyphTypeface , float fontRenderingEmSize , int length )
= > new SKPositionedGlyphRunBuffer ( glyphTypeface , fontRenderingEmSize , length ) ;
var glyphTypefaceImpl = glyphTypeface as GlyphTypefaceImpl ;
private abstract class SKGlyphRunBufferBase : IGlyphRunBuffer
{
protected readonly SKTextBlobBuilder _ builder ;
protected readonly SKFont _f ont ;
var font = new SKFont
{
LinearMetrics = true ,
Subpixel = true ,
Edging = SKFontEdging . SubpixelAntialias ,
Hinting = SKFontHinting . Full ,
Size = ( float ) fontRenderingEmSize ,
Typeface = glyphTypefaceImpl . Typeface ,
Embolden = ( glyphTypefaceImpl . FontSimulations & FontSimulations . Bold ) ! = 0 ,
SkewX = ( glyphTypefaceImpl . FontSimulations & FontSimulations . Oblique ) ! = 0 ? - 0.2f : 0
} ;
var builder = new SKTextBlobBuilder ( ) ;
public SKGlyphRunBufferBase ( IGlyphTypeface glyphTypeface , float fontRenderingEmSize , int length )
var count = glyphIndices . Count ;
if ( glyphOffsets ! = null & & glyphAdvances ! = null )
{
_ builder = new SKTextBlobBuilder ( ) ;
var runBuffer = builder . AllocatePositionedRun ( font , count ) ;
var glyphTypefaceImpl = ( GlyphTypefaceImpl ) glyphTypeface ;
var glyphSpan = runBuffer . GetGlyphSpan ( ) ;
var positionSpan = runBuffer . GetPositionSpan ( ) ;
_f ont = new SKFont
{
Subpixel = true ,
Edging = SKFontEdging . SubpixelAntialias ,
Hinting = SKFontHinting . Full ,
LinearMetrics = true ,
Size = fontRenderingEmSize ,
Typeface = glyphTypefaceImpl . Typeface ,
Embolden = glyphTypefaceImpl . IsFakeBold ,
SkewX = glyphTypefaceImpl . IsFakeItalic ? - 0.2f : 0
} ;
}
var currentX = 0.0 ;
public abstract Span < ushort > GlyphIndices { get ; }
for ( int i = 0 ; i < glyphOffsets . Count ; i + + )
{
var offset = glyphOffsets [ i ] ;
public IGlyphRunImpl Build ( )
{
return new GlyphRunImpl ( _ builder . Build ( ) ) ;
}
}
glyphSpan [ i ] = glyphIndices [ i ] ;
private sealed class SKGlyphRunBuffer : SKGlyphRunBufferBase
{
private readonly SKRunBuffer _ buffer ;
positionSpan [ i ] = new SKPoint ( ( float ) ( currentX + offset . X ) , ( float ) offset . Y ) ;
public SKGlyphRunBuffer ( IGlyphTypeface glyphTypeface , float fontRenderingEmSize , int length ) : base ( glyphTypeface , fontRenderingEmSize , length )
{
_ buffer = _ builder . AllocateRun ( _f ont , length , 0 , 0 ) ;
currentX + = glyphAdvances [ i ] ;
}
}
else
{
if ( glyphAdvances ! = null )
{
var runBuffer = builder . AllocateHorizontalRun ( font , count , 0 ) ;
public override Span < ushort > GlyphIndices = > _ buffer . GetGlyphSpan ( ) ;
}
var glyphSpan = runB uffer . GetGlyphSpan ( ) ;
var positionSpan = runBuffer . GetPositionSpan ( ) ;
private sealed class SKHorizontalGlyphRunBuffer : SKGlyphRunBufferBase , IHorizontalGlyphRunBuffer
{
private readonly SKHorizontalRunBuffer _ buffer ;
var currentX = 0.0 ;
public SKHorizontalGlyphRunBuffer ( IGlyphTypeface glyphTypeface , float fontRenderingEmSize , int length ) : base ( glyphTypeface , fontRenderingEmSize , length )
{
_ buffer = _ builder . AllocateHorizontalRun ( _f ont , length , 0 ) ;
}
for ( int i = 0 ; i < glyphOffsets . Count ; i + + )
{
glyphSpan [ i ] = glyphIndices [ i ] ;
public override Span < ushort > GlyphIndices = > _ buffer . GetGlyphSpan ( ) ;
positionSpan [ i ] = ( float ) currentX ;
public Span < float > GlyphPositions = > _ buffer . GetPositionSpan ( ) ;
}
currentX + = glyphAdvances [ i ] ;
}
}
else
{
var runBuffer = builder . AllocateRun ( font , count , 0 , 0 ) ;
private sealed class SKPositionedGlyphRunBuffer : SKGlyphRunBufferBase , IPositionedGlyphRunBuffer
{
private readonly SKPositionedRunBuffer _ buffer ;
var glyphSpan = runBuffer . GetGlyphSpan ( ) ;
public SKPositionedGlyphRunBuffer ( IGlyphTypeface glyphTypeface , float fontRenderingEmSize , int length ) : base ( glyphTypeface , fontRenderingEmSize , length )
{
_ buffer = _ builder . AllocatePositionedRun ( _f ont , length ) ;
for ( int i = 0 ; i < glyphOffsets . Count ; i + + )
{
glyphSpan [ i ] = glyphIndices [ i ] ;
}
}
}
public override Span < ushort > GlyphIndices = > _ buffer . GetGlyphSpan ( ) ;
public Span < PointF > GlyphPositions = > MemoryMarshal . Cast < SKPoint , PointF > ( _ buffer . GetPositionSpan ( ) ) ;
return new GlyphRunImpl ( builder . Build ( ) ) ;
}
}
}