public static void DrawQuests(SKCanvas c, BaseBundle icon) { using SKPaint paint = new SKPaint { IsAntialias = true, FilterQuality = SKFilterQuality.High, TextSize = 27, Color = SKColors.White, TextAlign = SKTextAlign.Left, Typeface = Text.TypeFaces.BundleDisplayNameTypeface }; int y = icon.HeaderHeight + 50; foreach (Quest q in icon.Quests) { DrawQuestBackground(c, icon, y, true); paint.TextSize = 27; paint.ImageFilter = null; paint.Color = SKColors.White; paint.TextAlign = SKTextAlign.Left; paint.Typeface = Text.TypeFaces.BundleDisplayNameTypeface; if (!string.IsNullOrEmpty(q.Description)) { if ((ELanguage)Properties.Settings.Default.AssetsLanguage == ELanguage.Arabic) { SKShaper shaper = new SKShaper(paint.Typeface); float shapedTextWidth; while (true) { SKShaper.Result shapedText = shaper.Shape(q.Description, paint); shapedTextWidth = shapedText.Points[^ 1].X + paint.TextSize / 2f;
/// <summary> /// Gets a <see cref="SKPaint"/> containing information needed to render text. /// </summary> /// <remarks> /// This modifies and returns the local <see cref="paint"/> instance. /// </remarks> /// <param name="fontFamily">The font family.</param> /// <param name="fontSize">The font size.</param> /// <param name="fontWeight">The font weight.</param> /// <param name="shaper">The font shaper.</param> /// <returns>The paint.</returns> private SKPaint GetTextPaint(string fontFamily, double fontSize, double fontWeight, out SKShaper shaper) { var fontDescriptor = new FontDescriptor(fontFamily, fontWeight); if (!this.typefaceCache.TryGetValue(fontDescriptor, out var typeface)) { typeface = SKTypeface.FromFamilyName(fontFamily, new SKFontStyle((int)fontWeight, (int)SKFontStyleWidth.Normal, SKFontStyleSlant.Upright)); this.typefaceCache.Add(fontDescriptor, typeface); } if (this.UseTextShaping) { if (!this.shaperCache.TryGetValue(fontDescriptor, out shaper)) { shaper = new SKShaper(typeface); this.shaperCache.Add(fontDescriptor, shaper); } } else { shaper = null; } this.paint.Typeface = typeface; this.paint.TextSize = this.Convert(fontSize); this.paint.IsAntialias = true; this.paint.Style = SKPaintStyle.Fill; this.paint.HintingLevel = this.RendersToScreen ? SKPaintHinting.Full : SKPaintHinting.NoHinting; this.paint.SubpixelText = this.RendersToScreen; return(this.paint); }
/// <summary> /// Measures text using the specified <see cref="SKShaper"/> and <see cref="SKPaint"/>. /// </summary> /// <param name="text">The text to measure.</param> /// <param name="shaper">The text shaper.</param> /// <param name="paint">The paint.</param> /// <returns>The width of the text when rendered using the specified shaper and paint.</returns> private float MeasureText(string text, SKShaper shaper, SKPaint paint) { if (!this.UseTextShaping) { return(paint.MeasureText(text)); } // we have to get a bit creative here as SKShaper does not offer a direct overload for this. // see also https://github.com/mono/SkiaSharp/blob/master/source/SkiaSharp.HarfBuzz/SkiaSharp.HarfBuzz.Shared/SKShaper.cs using var buffer = new HarfBuzzSharp.Buffer(); switch (paint.TextEncoding) { case SKTextEncoding.Utf8: buffer.AddUtf8(text); break; case SKTextEncoding.Utf16: buffer.AddUtf16(text); break; case SKTextEncoding.Utf32: buffer.AddUtf32(text); break; default: throw new NotSupportedException("TextEncoding is not supported."); } buffer.GuessSegmentProperties(); shaper.Shape(buffer, paint); return(buffer.GlyphPositions.Sum(gp => gp.XAdvance) * paint.TextSize / 512); }
public void DrawShapedTextExtensionMethodDraws() { using (var bitmap = new SKBitmap(new SKImageInfo(512, 512))) using (var canvas = new SKCanvas(bitmap)) using (var tf = SKTypeface.FromFile(Path.Combine(PathToFonts, "content-font.ttf"))) using (var shaper = new SKShaper(tf)) using (var paint = new SKPaint { IsAntialias = true, TextSize = 64, Typeface = tf }) { canvas.Clear(SKColors.White); canvas.DrawShapedText(shaper, "متن", 100, 200, paint); canvas.Flush(); Assert.Equal(SKColors.Black, bitmap.GetPixel(110, 210)); Assert.Equal(SKColors.Black, bitmap.GetPixel(127, 196)); Assert.Equal(SKColors.Black, bitmap.GetPixel(142, 197)); Assert.Equal(SKColors.Black, bitmap.GetPixel(155, 195)); Assert.Equal(SKColors.Black, bitmap.GetPixel(131, 181)); Assert.Equal(SKColors.White, bitmap.GetPixel(155, 190)); Assert.Equal(SKColors.White, bitmap.GetPixel(110, 200)); } }
public void ShapeTest() { using var bmp = new Bitmap(600, 400); using var canvas = new SKCanvas(bmp.skBitmap); using var typeface = SKFontManager.Default.MatchCharacter('中'); using var paint = new SKPaint(); paint.IsAntialias = true; paint.TextEncoding = SKTextEncoding.Utf16; paint.TextSize = 30; paint.Color = new SKColor(255, 0, 0, 255); paint.Style = SKPaintStyle.Fill; paint.Typeface = typeface; var src = "Hello Future! 你好,未来!"; canvas.DrawText(src, 0, 100, paint); using var shaper = new SKShaper(typeface); paint.TextAlign = SKTextAlign.Right; //paint.TextEncoding = SKTextEncoding.GlyphId; //Not implemented canvas.DrawShapedText(shaper, src, 0, 200, paint); using var fs = File.OpenWrite("A_document.jpg"); bmp.Save(fs, ImageFormat.Jpeg); }
public static SKPoint[] MeasureCharacters(string text, SKTypeface font, int fontSize, float xOffset = 0, float yOffset = 0) { using var paint = SkiaTextExtensions.CreateTextPaint(font, fontSize, SKColors.Black); using var shaper = new SKShaper(font); var result = shaper.Shape(text, xOffset, yOffset, paint); return(result.Points); }
protected void DrawLabels(SKCanvas canvas, SKPoint[] points, SKSize itemSize, int height, float footerHeight) { for (int i = 0; i < this.Entries.Count(); i++) { var entry = this.Entries.ElementAt(i); var point = points[i]; if (!string.IsNullOrEmpty(entry.Label)) { using (var paint = new SKPaint()) { paint.TextSize = this.LabelTextSize; paint.IsAntialias = true; paint.Color = entry.TextColor; paint.IsStroke = false; var bounds = new SKRect(); var text = entry.Label; paint.MeasureText(text, ref bounds); if (bounds.Width > itemSize.Width) { text = text.Substring(0, Math.Min(3, text.Length)); paint.MeasureText(text, ref bounds); } if (bounds.Width > itemSize.Width) { text = text.Substring(0, Math.Min(1, text.Length)); paint.MeasureText(text, ref bounds); } //canvas.DrawText("asdf", point.X - (bounds.Width / 2), height - this.Margin + (this.LabelTextSize / 2), paint); using (var tf = SKFontManager.Default.MatchCharacter('م')) using (var shaper = new SKShaper(tf)) using (var paint1 = new SKPaint { TextSize = 30, Typeface = tf }) { //canvas.Clear(SKColors.White); //canvas.DrawShapedText(shaper, "سلام", 100, 200, paint1); paint.Typeface = tf; var balanceValue = 35; canvas.DrawShapedText(shaper, text, point.X - (bounds.Width / 2) - balanceValue, height - this.Margin + (this.LabelTextSize / 2) - balanceValue, paint); } } } } }
public void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args) { try { SKImageInfo info = args.Info; SKSurface surface = args.Surface; SKCanvas canvas = surface.Canvas; Assembly assembly = GetType().GetTypeInfo().Assembly; if (_saveBitmap == null) { _saveBitmap = new SKBitmap(info.Width, info.Height); } SKBitmap bitmap = new SKBitmap(Math.Max(_saveBitmap.Width, info.Width), Math.Max(_saveBitmap.Height, info.Height)); float x = info.Width / 3; float y = (float)(info.Height / 1.5); using (SKCanvas c = new SKCanvas(bitmap)) { foreach (SKPath p in _completedPaths) { c.DrawPath(p, paint); } foreach (SKPath p in _inProgressPaths.Values) { c.DrawPath(p, paint); } } canvas.Clear(); canvas.DrawBitmap(bitmap, 0, 0); var emoji = _vm.Image; int exEmoji = 0x1f600; paint.Typeface = SKFontManager.CreateDefault().MatchCharacter(exEmoji); paint.TextSize = 210.0f; var tf = SKFontManager.CreateDefault().MatchCharacter(exEmoji); var shaper = new SKShaper(tf); canvas.DrawShapedText(shaper, emoji, x, y, paint); } catch { } }
protected override void OnDrawSample(SKCanvas canvas, int width, int height) { canvas.DrawColor(SKColors.White); using var tf = SKFontManager.Default.MatchCharacter('م') ?? SKTypeface.FromStream(SampleMedia.Fonts.EmbeddedFont); using var paint = new SKPaint { IsAntialias = true, TextSize = 64 }; using var arabicPaint = new SKPaint { IsAntialias = true, TextSize = 64, Typeface = tf }; // unshaped canvas.DrawText("Unshaped:", 100, 100, paint); canvas.DrawText("مرحبا بالعالم", 100, 180, arabicPaint); // shaped using var shaper = new SKShaper(tf); canvas.DrawText("Shaped:", 100, 300, paint); canvas.DrawShapedText(shaper, "مرحبا بالعالم", 100, 380, arabicPaint); }
public void Draw(SKCanvas c) { c.DrawRect(new SKRect(0, 0, Width, Height), new SKPaint { IsAntialias = true, FilterQuality = SKFilterQuality.High, Shader = SKShader.CreateLinearGradient( new SKPoint(Width / 2, Height), new SKPoint(Width, Height / 4), new SKColor[2] { SKColor.Parse("01369C"), SKColor.Parse("1273C8") }, SKShaderTileMode.Clamp) }); int textSize = 45; SKPaint namePaint = new SKPaint { IsAntialias = true, FilterQuality = SKFilterQuality.High, Typeface = Text.TypeFaces.DisplayNameTypeface, TextSize = textSize, Color = SKColors.White, TextAlign = SKTextAlign.Left }; SKPaint optionPaint = new SKPaint { IsAntialias = true, FilterQuality = SKFilterQuality.High, Typeface = Text.TypeFaces.DisplayNameTypeface, TextSize = 20, Color = SKColor.Parse("EEFFFF"), TextAlign = SKTextAlign.Left }; if ((ELanguage)Properties.Settings.Default.AssetsLanguage == ELanguage.Arabic) { SKShaper shaper = new SKShaper(namePaint.Typeface); float shapedTextWidth; while (true) { SKShaper.Result shapedText = shaper.Shape(OptionDisplayName, namePaint); shapedTextWidth = shapedText.Points[^ 1].X + namePaint.TextSize / 2f;
public void CorrectlyShapesArabicScript() { var clusters = new uint[] { 4, 2, 0 }; var codepoints = new uint[] { 629, 668, 891 }; var points = new SKPoint[] { new SKPoint(0, 0), new SKPoint(28.375f, 0), new SKPoint(42.125f, 0) }; using (var tf = SKTypeface.FromFile(Path.Combine(PathToFonts, "content-font.ttf"))) using (var shaper = new SKShaper(tf)) using (var paint = new SKPaint { IsAntialias = true, TextSize = 64, Typeface = tf }) { var result = shaper.Shape("متن", paint); Assert.Equal(clusters, result.Clusters); Assert.Equal(codepoints, result.Codepoints); Assert.Equal(points, result.Points); } }
public static void DrawCenteredMultilineText(SKCanvas canvas, string text, int maxLineCount, int size, int margin, ETextSide side, SKRect area, SKPaint paint) { float lineHeight = paint.TextSize * 1.2f; List <Line> lines = SplitLines(text, paint, area.Width - margin); if (lines == null) { return; } if (lines.Count <= maxLineCount) { maxLineCount = lines.Count; } float height = maxLineCount * lineHeight; float y = area.MidY - height / 2; SKShaper shaper = (ELanguage)Settings.Default.AssetsLanguage == ELanguage.Arabic ? new SKShaper(paint.Typeface) : null; for (int i = 0; i < maxLineCount; i++) { Line line = lines[i]; y += lineHeight; float x = side switch { ETextSide.Center => area.MidX - line.Width / 2, ETextSide.Right => size - margin - line.Width, ETextSide.Left => margin, _ => area.MidX - line.Width / 2 }; string lineText = line.Value.TrimEnd(); if (shaper == null) { canvas.DrawText(lineText, x, y, paint); } else { if (side == ETextSide.Center) { SKShaper.Result shapedText = shaper.Shape(lineText, paint); float shapedTextWidth = shapedText.Points[^ 1].X + paint.TextSize / 2f;
public void DrawShapedTextExtensionMethodDraws() { using (var surface = SKSurface.Create(new SKImageInfo(512, 512))) using (var tf = SKTypeface.FromFile(Path.Combine(PathToFonts, "content-font.ttf"))) using (var shaper = new SKShaper(tf)) using (var paint = new SKPaint { IsAntialias = true, TextSize = 64, Typeface = tf }) { surface.Canvas.Clear(SKColors.White); surface.Canvas.DrawShapedText(shaper, "متن", 100, 200, paint); surface.Canvas.Flush(); using (var img = surface.Snapshot()) using (var data = img.Encode(SKEncodedImageFormat.Png, 100)) using (var stream = File.OpenWrite(Path.Combine(PathToImages, "test.png"))) { data.AsStream().CopyTo(stream); } } }
private void DrawHeaderText(SKCanvas c) { using SKPaint paint = new SKPaint { IsAntialias = true, FilterQuality = SKFilterQuality.High, Typeface = Text.TypeFaces.BundleDisplayNameTypeface, TextSize = 50, Color = SKColors.White, TextAlign = SKTextAlign.Left, }; string text = DisplayName.ToUpper(); int x = 300; if ((ELanguage)Properties.Settings.Default.AssetsLanguage == ELanguage.Arabic) { SKShaper shaper = new SKShaper(paint.Typeface); float shapedTextWidth; while (true) { SKShaper.Result shapedText = shaper.Shape(text, paint); shapedTextWidth = shapedText.Points[^ 1].X + paint.TextSize / 2f;
public static async Task Run( [QueueTrigger("create-hero")] KeyValuePair <string, string> hf, [Blob("heroimages")] CloudBlobContainer heroContainer, [Blob("hashflags")] CloudBlobContainer hashflagsContainer, [Queue("tweet")] ICollector <KeyValuePair <string, string> > tweetCollector, ILogger log) { log.LogInformation($"Function executed at: {DateTime.Now}"); var hashtag = '#' + hf.Key; var textSize = GetAdjustedFont(hashtag); var info = new SKImageInfo(ImageWidth, ImageHeight); using var surface = SKSurface.Create(info); var canvas = surface.Canvas; canvas.Clear(SKColors.White); #region hashtag var typefaces = hf.Key.Select(character => SKFontManager.CreateDefault().MatchCharacter(FontFamily, character)).ToList(); using var tf = typefaces.FirstOrDefault(t => t.FamilyName != FontFamily) ?? SKTypeface.FromFamilyName(FontFamily); using var shaper = new SKShaper(tf); var paint = new SKPaint { IsAntialias = true, Color = new SKColor(29, 161, 242), TextSize = textSize, Typeface = tf }; var bounds = new SKRect(); paint.MeasureText(hashtag, ref bounds); var point = GetPoint(hashtag, bounds.Height, bounds.Width); canvas.DrawShapedText(shaper, hashtag, point.X, point.Y, paint); #endregion #region hashflag await using var stream = new MemoryStream(); await hashflagsContainer.GetBlockBlobReference(hf.Value).DownloadToStreamAsync(stream); stream.Seek(0, SeekOrigin.Begin); var hashflagImage = SKBitmap.Decode(stream); var x = IsRtl(hashtag) ? point.X - HashflagSize - 10 : point.X + bounds.Width + 10; var y = (ImageHeight - HashflagSize) / 2; canvas.DrawBitmap(hashflagImage, x, y); #endregion #region watermark paint = new SKPaint { Color = new SKColor(20, 23, 26, 127), TextSize = 18, IsAntialias = true, Typeface = tf }; canvas.DrawShapedText(shaper, "@HashflagArchive", 900, 575, paint); #endregion canvas.Flush(); await heroContainer.CreateIfNotExistsAsync(); var heroBlob = heroContainer.GetBlockBlobReference(hf.Key); heroBlob.Properties.ContentType = "image/png"; await heroBlob.UploadFromStreamAsync(ToStream(surface)); tweetCollector.Add(hf); }
public static void DrawCaptionLabels(this SKCanvas canvas, string label, SKColor labelColor, bool labelIsUnicode, char unicodeLang, string value, SKColor valueColor, float textSize, SKPoint point, SKTextAlign horizontalAlignment, SKTypeface typeface, out SKRect totalBounds) { var hasLabel = !string.IsNullOrEmpty(label); var hasValueLabel = !string.IsNullOrEmpty(value); totalBounds = new SKRect(); if (hasLabel || hasValueLabel) { var hasOffset = hasLabel && hasValueLabel; var captionMargin = textSize * 0.60f; var space = hasOffset ? captionMargin : 0; if (hasLabel) { using (var paint = new SKPaint { TextSize = textSize, IsAntialias = true, Color = labelColor, IsStroke = false, TextAlign = horizontalAlignment, Typeface = typeface }) { var bounds = new SKRect(); var text = label; paint.MeasureText(text, ref bounds); var y = point.Y - ((bounds.Top + bounds.Bottom) / 2) - space; if (labelIsUnicode) { using (var tf = SKFontManager.Default.MatchCharacter(unicodeLang)) using (var shaper = new SKShaper(tf)) { canvas.DrawShapedText(shaper, text, 0, 0, paint); } } else { canvas.DrawText(text, point.X, y, paint); } var labelBounds = GetAbsolutePositionRect(point.X, y, bounds, horizontalAlignment); totalBounds = labelBounds.Standardized; } } if (hasValueLabel) { using (var paint = new SKPaint() { TextSize = textSize, IsAntialias = true, FakeBoldText = true, Color = valueColor, IsStroke = false, TextAlign = horizontalAlignment, Typeface = typeface }) { var bounds = new SKRect(); var text = value; paint.MeasureText(text, ref bounds); var y = point.Y - ((bounds.Top + bounds.Bottom) / 2) + space; canvas.DrawText(text, point.X, y, paint); var valueBounds = GetAbsolutePositionRect(point.X, y, bounds, horizontalAlignment); if (totalBounds.IsEmpty) { totalBounds = valueBounds; } else { totalBounds.Union(valueBounds); } } } } }
public static void DrawCaptionLabels(this SKCanvas canvas, string label, SKColor labelColor, string value, SKColor valueColor, float textSize, SKPoint point, SKTextAlign horizontalAlignment) { var hasLabel = !string.IsNullOrEmpty(label); var hasValueLabel = !string.IsNullOrEmpty(value); if (hasLabel || hasValueLabel) { var hasOffset = hasLabel && hasValueLabel; var captionMargin = textSize * 0.60f; var space = hasOffset ? captionMargin : 0; if (hasLabel) { using (var paint = new SKPaint() { TextSize = textSize, IsAntialias = true, Color = labelColor, IsStroke = false, //TextAlign = horizontalAlignment, }) { var bounds = new SKRect(); var text = label; paint.MeasureText(text, ref bounds); var y = point.Y - ((bounds.Top + bounds.Bottom) / 2) - space; //canvas.DrawText(text, point.X, y, paint); using (var tf = SKFontManager.Default.MatchCharacter('م')) using (var shaper = new SKShaper(tf)) using (var paint1 = new SKPaint { TextSize = 30, Typeface = tf }) { //canvas.Clear(SKColors.White); //canvas.DrawShapedText(shaper, "سلام", 100, 200, paint1); paint.Typeface = tf; var balaceValue = 0; if (horizontalAlignment == SKTextAlign.Right) { if (text.Length <= 5) { balaceValue = 60; } else { var factor = (System.Math.Abs(text.Length - 5)); balaceValue = factor * 10 + 90; } } canvas.DrawShapedText(shaper, text, point.X - balaceValue, y, paint); } } } if (hasValueLabel) { using (var paint = new SKPaint() { TextSize = textSize, IsAntialias = true, FakeBoldText = true, Color = valueColor, IsStroke = false, TextAlign = horizontalAlignment, }) { var bounds = new SKRect(); var text = value; paint.MeasureText(text, ref bounds); var y = point.Y - ((bounds.Top + bounds.Bottom) / 2) + space; canvas.DrawText(text, point.X, y, paint); } } } }
public SKData DrawHistogram(string referenceName, int zoom, int chunk) { var refer = _service._references.FirstOrDefault(r => r.Name == referenceName); if (chunk == 0 && zoom == 10) { LoadReference(referenceName); } using var surface = SKSurface.Create(new SKImageInfo(refer.Length * zoom, 220)); using SKCanvas canvas = surface.Canvas; canvas.Clear(); using SKPaint paint = new SKPaint { Style = SKPaintStyle.StrokeAndFill, Color = SKColors.Blue, StrokeWidth = 1 }; using SKPaint linePaint = new SKPaint { Style = SKPaintStyle.Stroke, Color = SKColors.Black, StrokeWidth = 1 }; using SKPaint dashPaint = new SKPaint { Style = SKPaintStyle.Stroke, Color = SKColors.Black, StrokeWidth = 1, PathEffect = SKPathEffect.CreateDash(new[] { 20f, 5f }, 0) }; var histData = _service._histograms[refer.Name]; var scale = (float)(100 / histData.Average()); for (int i = 0; i < refer.Length; i++) { canvas.DrawRect(i * zoom + 5, 200 - (histData[i] * scale), zoom, histData[i] * scale, paint); } canvas.DrawLine(5, 0, 5, 200, linePaint); canvas.DrawLine(5, 199, refer.Length * zoom, 199, linePaint); var average = (int)(Math.Round(histData.Average())); canvas.DrawLine(5, average * scale, refer.Length * zoom, average * scale, dashPaint); using SKPaint textPaint = new SKPaint { Style = SKPaintStyle.StrokeAndFill, Color = SKColors.Black, StrokeWidth = 1, TextSize = 20, Typeface = SKTypeface.FromFamilyName("Courier New"), SubpixelText = true }; canvas.DrawText(average.ToString(), 6, average * scale - 2, textPaint); var cnt = textPaint.MeasureText("ACGT"); if (zoom == 10) { textPaint.TextSize = textPaint.TextSize * 40 / cnt; var shaper = new SKShaper(SKTypeface.FromFamilyName("Courier New")); canvas.DrawShapedText(shaper, reference, 5, 215, textPaint); } var width = (chunk + 1) * WIDTH * zoom > refer.Length * zoom ? refer.Length * zoom % WIDTH : WIDTH; SKPixmap pixmap = surface.Snapshot().Subset(SKRectI.Create(chunk * WIDTH, 0, width, canvas.DeviceClipBounds.Height)).PeekPixels(); var options = new SKWebpEncoderOptions(SKWebpEncoderCompression.Lossless, 100); return(pixmap.Encode(options)); }