diff --git a/source/SkiaSharp.HarfBuzz/SkiaSharp.HarfBuzz.Shared/CanvasExtensions.cs b/source/SkiaSharp.HarfBuzz/SkiaSharp.HarfBuzz.Shared/CanvasExtensions.cs index d372bb53603..4f9d304ff3b 100644 --- a/source/SkiaSharp.HarfBuzz/SkiaSharp.HarfBuzz.Shared/CanvasExtensions.cs +++ b/source/SkiaSharp.HarfBuzz/SkiaSharp.HarfBuzz.Shared/CanvasExtensions.cs @@ -53,8 +53,17 @@ public static void DrawShapedText(this SKCanvas canvas, SKShaper shaper, string // build using var textBlob = builder.Build(); + // adjust alignment + var xOffset = 0f; + if (paint.TextAlign != SKTextAlign.Left) { + var width = result.Width; + if (paint.TextAlign == SKTextAlign.Center) + width *= 0.5f; + xOffset -= width; + } + // draw the text - canvas.DrawText(textBlob, 0, 0, paint); + canvas.DrawText(textBlob, xOffset, 0, paint); } } } diff --git a/source/SkiaSharp.HarfBuzz/SkiaSharp.HarfBuzz.Shared/SKShaper.cs b/source/SkiaSharp.HarfBuzz/SkiaSharp.HarfBuzz.Shared/SKShaper.cs index 9f8bcd721b3..be299e977df 100644 --- a/source/SkiaSharp.HarfBuzz/SkiaSharp.HarfBuzz.Shared/SKShaper.cs +++ b/source/SkiaSharp.HarfBuzz/SkiaSharp.HarfBuzz.Shared/SKShaper.cs @@ -70,6 +70,7 @@ public Result Shape(Buffer buffer, float xOffset, float yOffset, SKPaint paint) var points = new SKPoint[len]; var clusters = new uint[len]; var codepoints = new uint[len]; + var xOffsetStart = xOffset; for (var i = 0; i < len; i++) { @@ -86,7 +87,9 @@ public Result Shape(Buffer buffer, float xOffset, float yOffset, SKPaint paint) yOffset += pos[i].YAdvance * textSizeY; } - return new Result(codepoints, clusters, points); + var width = xOffset - xOffsetStart; + + return new Result(codepoints, clusters, points, width); } public Result Shape(string text, SKPaint paint) => @@ -129,6 +132,7 @@ public Result() Codepoints = new uint[0]; Clusters = new uint[0]; Points = new SKPoint[0]; + Width = 0f; } public Result(uint[] codepoints, uint[] clusters, SKPoint[] points) @@ -136,13 +140,24 @@ public Result(uint[] codepoints, uint[] clusters, SKPoint[] points) Codepoints = codepoints; Clusters = clusters; Points = points; + Width = 0; + } + + public Result(uint[] codepoints, uint[] clusters, SKPoint[] points, float width) + { + Codepoints = codepoints; + Clusters = clusters; + Points = points; + Width = width; } - public uint[] Codepoints { get; private set; } + public uint[] Codepoints { get; } + + public uint[] Clusters { get; } - public uint[] Clusters { get; private set; } + public SKPoint[] Points { get; } - public SKPoint[] Points { get; private set; } + public float Width { get; } } } } diff --git a/tests/Tests/SKShaperTest.cs b/tests/Tests/SKShaperTest.cs index 2392f1a9ce1..97a631c7d0f 100644 --- a/tests/Tests/SKShaperTest.cs +++ b/tests/Tests/SKShaperTest.cs @@ -101,5 +101,52 @@ Blob GetFaceBlob(Face face, Tag tag) return new Blob(data, size, MemoryMode.Writeable, () => Marshal.FreeCoTaskMem(data)); } } + + [SkippableTheory] + [InlineData(SKTextAlign.Left, 300)] + [InlineData(SKTextAlign.Center, 162)] + [InlineData(SKTextAlign.Right, 23)] + public void TextAlignMovesTextPosition(SKTextAlign align, int offset) + { + var font = Path.Combine(PathToFonts, "segoeui.ttf"); + using var tf = SKTypeface.FromFile(font); + + using var bitmap = new SKBitmap(600, 200); + using var canvas = new SKCanvas(bitmap); + + canvas.Clear(SKColors.White); + + using var paint = new SKPaint(); + paint.Typeface = tf; + paint.IsAntialias = true; + paint.TextSize = 64; + paint.Color = SKColors.Black; + paint.TextAlign = align; + + canvas.DrawShapedText("SkiaSharp", 300, 100, paint); + + AssertTextAlign(bitmap, offset, 0); + } + + private static void AssertTextAlign(SKBitmap bitmap, int x, int y) + { + // [S]kia[S]har[p] + + Assert.Equal(SKColors.Black, bitmap.GetPixel(x + 6, y + 66)); + Assert.Equal(SKColors.Black, bitmap.GetPixel(x + 28, y + 87)); + Assert.Equal(SKColors.White, bitmap.GetPixel(x + 28, y + 66)); + Assert.Equal(SKColors.White, bitmap.GetPixel(x + 6, y + 87)); + + Assert.Equal(SKColors.Black, bitmap.GetPixel(x + 120, y + 66)); + Assert.Equal(SKColors.Black, bitmap.GetPixel(x + 142, y + 87)); + Assert.Equal(SKColors.White, bitmap.GetPixel(x + 142, y + 66)); + Assert.Equal(SKColors.White, bitmap.GetPixel(x + 120, y + 87)); + + Assert.Equal(SKColors.Black, bitmap.GetPixel(x + 246, y + 70)); + Assert.Equal(SKColors.Black, bitmap.GetPixel(x + 246, y + 113)); + Assert.Equal(SKColors.Black, bitmap.GetPixel(x + 271, y + 83)); + Assert.Equal(SKColors.White, bitmap.GetPixel(x + 258, y + 83)); + Assert.Equal(SKColors.White, bitmap.GetPixel(x + 258, y + 113)); + } } }