From 17da8ad14534a9630fd3e192187d2edf9cbde971 Mon Sep 17 00:00:00 2001 From: Tal Keren Date: Wed, 29 Dec 2021 23:53:14 +0200 Subject: [PATCH 1/3] DrawShapedText: Support SKPaint.TextAlign property --- .../SkiaSharp.HarfBuzz.Shared/CanvasExtensions.cs | 11 ++++++++++- .../SkiaSharp.HarfBuzz.Shared/SKShaper.cs | 11 +++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) 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..63884569ab4 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,13 +132,15 @@ public Result() Codepoints = new uint[0]; Clusters = new uint[0]; Points = new SKPoint[0]; + Width = 0f; } - public Result(uint[] codepoints, uint[] clusters, SKPoint[] points) + public Result(uint[] codepoints, uint[] clusters, SKPoint[] points, float width) { Codepoints = codepoints; Clusters = clusters; Points = points; + Width = width; } public uint[] Codepoints { get; private set; } @@ -143,6 +148,8 @@ public Result(uint[] codepoints, uint[] clusters, SKPoint[] points) public uint[] Clusters { get; private set; } public SKPoint[] Points { get; private set; } + + public float Width { get; private set; } } } } From dd0f50c39885e535e7f91eabd5c10d5c28b256b6 Mon Sep 17 00:00:00 2001 From: Tal Keren Date: Wed, 29 Dec 2021 23:53:35 +0200 Subject: [PATCH 2/3] Add test for DrawShapedText alignment --- tests/Tests/SKShaperTest.cs | 47 +++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) 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)); + } } } From 5398bfdebe06a2ec451829afbaccec8725de3d6e Mon Sep 17 00:00:00 2001 From: Matthew Leibowitz Date: Wed, 18 May 2022 23:21:41 +0700 Subject: [PATCH 3/3] don't break API --- .../SkiaSharp.HarfBuzz.Shared/SKShaper.cs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/source/SkiaSharp.HarfBuzz/SkiaSharp.HarfBuzz.Shared/SKShaper.cs b/source/SkiaSharp.HarfBuzz/SkiaSharp.HarfBuzz.Shared/SKShaper.cs index 63884569ab4..be299e977df 100644 --- a/source/SkiaSharp.HarfBuzz/SkiaSharp.HarfBuzz.Shared/SKShaper.cs +++ b/source/SkiaSharp.HarfBuzz/SkiaSharp.HarfBuzz.Shared/SKShaper.cs @@ -135,6 +135,14 @@ public Result() Width = 0f; } + 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; @@ -143,13 +151,13 @@ public Result(uint[] codepoints, uint[] clusters, SKPoint[] points, float width) Width = width; } - public uint[] Codepoints { get; private set; } + public uint[] Codepoints { get; } - public uint[] Clusters { get; private set; } + public uint[] Clusters { get; } - public SKPoint[] Points { get; private set; } + public SKPoint[] Points { get; } - public float Width { get; private set; } + public float Width { get; } } } }