Canvas: Font property not working for fonts registered with ConfigureFonts
aletfa opened this issue · 2 comments
In a MAUI Canvas try to draw some text with a font registered during the ConfigureFonts startup.
canvas.Font = new Microsoft.Maui.Graphics.Font("Dino");
canvas.DrawString("Hello", 10, 10, HorizontalAlignment.Center);
Expected result:
- Text rendered with expected Font
Current result:
- Text rendered with default Font
We had the same problem i.e. we have to set different Custom Font(s) depending upon some logic, so what I found that the DrawString method doesn't use IFont it uses FontPaint and setting IFont doesn't always override the default FontPaint object.
So I created a workaround,
- Create a new inherited class from SkiaCanvas e.g. MySkicCanvas
- Override IFont setter, here set FontPaint object using the Custom Font
- Create a new inherited class from BitmapExportContext e.g. MyBitmapExportContext
- in the inherited constructor inject MySkicCanvas while create ScalingCanvas object
- and while consuming MyBitmapExportContext.Canvas, always set the MyBitmapExportContext.Canvas.Font first then set MyBitmapExportContext.Canvas.FontSize and/or MyBitmapExportContext.Canvas.FontColor
Code snipped is in here
public class MySkiaCanvas : SkiaCanvas { public override IFont Font { set { base.CurrentState.FontPaint = new SKPaint { Color = SKColors.Black, IsAntialias = true, Typeface = SKTypeface.FromFile(value.Name) }; } } }
`
public class MyBitmapExportContext : BitmapExportContext
{
private SKBitmap? _bitmap;
private SKSurface _surface;
private ScalingCanvas _canvas;
public MyBitmapExportContext(int width, int height, float displayScale)
: base(width, height, 72)
{
_surface = SKSurface.Create(new SKImageInfo(width, height, SKColorType.Rgba8888, SKAlphaType.Premul));
_canvas = new ScalingCanvas(new MySkiaCanvas
{
Canvas = _surface.Canvas,
DisplayScale = displayScale
});
}
public override Microsoft.Maui.Graphics.ICanvas Canvas => _canvas;
public override IImage Image
{
get
{
return new SkiaImage(Bitmap);
}
}
public SKBitmap Bitmap
{
get
{
if (_bitmap == null)
{
_bitmap = SKBitmap.Decode(_surface.Snapshot().Encode());
}
return _bitmap;
}
}
public override void WriteToStream(Stream stream)
{
using var data = _surface.Snapshot().Encode(SKEncodedImageFormat.Png, 100);
data.SaveTo(stream);
}
protected override void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
_surface.Dispose();
_bitmap?.Dispose();
_bitmap = null;
base.Dispose(disposing);
//we are not setting disposedValue value to true here as its done in the base method
}
}
}
}
`