From 909bb2eb0538a9b8114213242ff5d8537bfb699d Mon Sep 17 00:00:00 2001 From: Alby Blyth Date: Thu, 25 Jan 2024 14:33:33 +1000 Subject: [PATCH 1/2] Update graphics adapter to use correct calculated height --- .../Adapters/GraphicsAdapter.cs | 434 +++++++++--------- 1 file changed, 211 insertions(+), 223 deletions(-) diff --git a/Source/HtmlRenderer.SkiaSharp/Adapters/GraphicsAdapter.cs b/Source/HtmlRenderer.SkiaSharp/Adapters/GraphicsAdapter.cs index c6e45ba86..6ec065bc4 100644 --- a/Source/HtmlRenderer.SkiaSharp/Adapters/GraphicsAdapter.cs +++ b/Source/HtmlRenderer.SkiaSharp/Adapters/GraphicsAdapter.cs @@ -19,238 +19,226 @@ namespace TheArtOfDev.HtmlRenderer.SkiaSharp.Adapters { - /// - /// Adapter for Skia Graphics for core. - /// - internal sealed class GraphicsAdapter : RGraphics - { - #region Fields and Consts - - /// - /// The wrapped SkiaSharp graphics object - /// - private readonly SKCanvas _g; - - /// - /// if to release the graphics object on dispose - /// - private readonly bool _releaseGraphics; - - /// - /// Used to measure and draw strings - /// - private static readonly SKTextAlign _stringFormat; - - #endregion - - - static GraphicsAdapter() - { - _stringFormat = new SKTextAlign(); - //_stringFormat.Alignment = XStringAlignment.Near; - //_stringFormat.LineAlignment = XLineAlignment.Near; - _stringFormat = SKTextAlign.Left; - } - - /// - /// Init. - /// - /// the win forms graphics object to use - /// optional: if to release the graphics object on dispose (default - false) - public GraphicsAdapter(SKCanvas g, bool releaseGraphics = false) - : base(SkiaSharpAdapter.Instance, new RRect(0, 0, double.MaxValue, double.MaxValue)) - { - ArgChecker.AssertArgNotNull(g, "g"); - - _g = g; - _releaseGraphics = releaseGraphics; - } - - public override void PopClip() - { - _clipStack.Pop(); - _g.Restore(); - } - - public override void PushClip(RRect rect) - { - _clipStack.Push(rect); - _g.Save(); - _g.ClipRect(Utils.Convert(rect)); - } - - public override void PushClipExclude(RRect rect) - { } - - bool _antiAlias = true; - public override Object SetAntiAliasSmoothingMode() - { - /* + /// + /// Adapter for Skia Graphics for core. + /// + internal sealed class GraphicsAdapter : RGraphics + { + #region Fields and Consts + + /// + /// The wrapped SkiaSharp graphics object + /// + private readonly SKCanvas _g; + + /// + /// if to release the graphics object on dispose + /// + private readonly bool _releaseGraphics; + + /// + /// Used to measure and draw strings + /// + private static readonly SKTextAlign _stringFormat; + + #endregion + + + static GraphicsAdapter() + { + _stringFormat = new SKTextAlign(); + //_stringFormat.Alignment = XStringAlignment.Near; + //_stringFormat.LineAlignment = XLineAlignment.Near; + _stringFormat = SKTextAlign.Left; + } + + /// + /// Init. + /// + /// the win forms graphics object to use + /// optional: if to release the graphics object on dispose (default - false) + public GraphicsAdapter(SKCanvas g, bool releaseGraphics = false) + : base(SkiaSharpAdapter.Instance, new RRect(0, 0, double.MaxValue, double.MaxValue)) + { + ArgChecker.AssertArgNotNull(g, "g"); + + _g = g; + _releaseGraphics = releaseGraphics; + } + + public override void PopClip() + { + _clipStack.Pop(); + _g.Restore(); + } + + public override void PushClip(RRect rect) + { + _clipStack.Push(rect); + _g.Save(); + _g.ClipRect(Utils.Convert(rect)); + } + + public override void PushClipExclude(RRect rect) + { } + + bool _antiAlias = true; + public override Object SetAntiAliasSmoothingMode() + { + /* var prevMode = _; _g.SmoothingMode = XSmoothingMode.AntiAlias; return prevMode; */ - var prevMode = _antiAlias; - _antiAlias = true; - return prevMode; - } + var prevMode = _antiAlias; + _antiAlias = true; + return prevMode; + } - public override void ReturnPreviousSmoothingMode(Object prevMode) - { - /* + public override void ReturnPreviousSmoothingMode(Object prevMode) + { + /* if (prevMode != null) { _g.SmoothingMode = (XSmoothingMode)prevMode; }*/ - if (prevMode != null) - { - _antiAlias = (bool)prevMode; - } - } - - public override RSize MeasureString(string str, RFont font) - { - var fontAdapter = (FontAdapter)font; - var realFont = fontAdapter.Font; - var p = new SKPaint(realFont); - var boundingRect = new SKRect(); - var measuredWidth = p.MeasureText(str, ref boundingRect); - - float width; - if (str == " ") - { - width = measuredWidth; - } - else - { - //The bounding rect width looks a bit odd. We'll take the midpoint until I can work out why this is. - width = measuredWidth;// measuredWidth;// (boundingRect.Width + measuredWidth) / 2; - } - - var height = realFont.Metrics.XMax + realFont.Metrics.XMin; - - if (font.Height < 0) - { - var descent = realFont.Metrics.Descent; - fontAdapter.SetMetrics((int)Math.Round(height, MidpointRounding.AwayFromZero), (int)Math.Round((height - descent + 1f), MidpointRounding.AwayFromZero)); - } - - return new RSize(width, height); - } - - public override void MeasureString(string str, RFont font, double maxWidth, out int charFit, out double charFitWidth) - { - // there is no need for it - used for text selection - throw new NotSupportedException(); - } - - public override void DrawString(string str, RFont font, RColor color, RPoint point, RSize size, bool rtl) - { - //var xBrush = ((BrushAdapter)_adapter.GetSolidBrush(color)).Brush; - var skiaFont = ((FontAdapter)font).Font; - var p = new SKPaint - { - IsAntialias = _antiAlias, - FilterQuality = SKFilterQuality.Medium, - Color = Utils.Convert(color) - }; - _g.DrawText(str, (float)point.X, (float)point.Y - skiaFont.Metrics.Ascent, skiaFont, p); - } - - public override RBrush GetTextureBrush(RImage image, RRect dstRect, RPoint translateTransformLocation) - { - return new BrushAdapter(new XTextureBrush(((ImageAdapter)image).Image, Utils.Convert(dstRect), Utils.Convert(translateTransformLocation))); - } - - public override RGraphicsPath GetGraphicsPath() - { - return new GraphicsPathAdapter(); - } - - public override void Dispose() - { - if (_releaseGraphics) - _g.Dispose(); - } - - - #region Delegate graphics methods - - public override void DrawLine(RPen pen, double x1, double y1, double x2, double y2) - { - _g.DrawLine((float)x1, (float)y1, (float)x2, (float)y2, GetPaint(pen)); - } - - public override void DrawRectangle(RPen pen, double x, double y, double width, double height) - { - _g.DrawRect((float)x, (float)y, (float)width, (float)height, GetPaint(pen)); - } - - public override void DrawRectangle(RBrush brush, double x, double y, double width, double height) - { - var untypedBrush = ((BrushAdapter)brush).Brush; - if (untypedBrush is XTextureBrush textureBrush) - { - textureBrush.DrawRectangle(_g, (float)x, (float)y, (float)width, (float)height); - } - else if (untypedBrush is SKBrush skBrush) - { - var p = skBrush.GetPaint().Clone(); - p.IsAntialias = _antiAlias; - _g.DrawRect((float)x, (float)y, (float)width, (float)height, p); - } - } - - public override void DrawImage(RImage image, RRect destRect, RRect srcRect) - { - ((ImageAdapter)image).DrawImage(_g, Utils.Convert(destRect), Utils.Convert(srcRect)); - } - - public override void DrawImage(RImage image, RRect destRect) - { - ((ImageAdapter)image).DrawImage(_g, Utils.Convert(destRect)); - } - - public override void DrawPath(RPen pen, RGraphicsPath path) - { - _g.DrawPath(((GraphicsPathAdapter)path).GraphicsPath, GetPaint(pen)); - } - - public override void DrawPath(RBrush brush, RGraphicsPath path) - { - _g.DrawPath(((GraphicsPathAdapter)path).GraphicsPath, GetPaint(brush)); - } - - public override void DrawPolygon(RBrush brush, RPoint[] points) - { - var p = GetPaint(brush); - - if (points != null && points.Length > 0) - { - //(XBrush)((BrushAdapter)brush).Brush - var path = new SKPath(); - path.AddPoly(Utils.Convert(points)); - _g.DrawPath(path, p); - } - } - - private SKPaint GetPaint(RBrush brush) - { - SKBrush skBrush = (SKBrush)((BrushAdapter)brush).Brush; - var p = skBrush.GetPaint().Clone(); - p.IsAntialias = _antiAlias; - return p; - } - - private SKPaint GetPaint(RPen pen) - { - var skPaint =((PenAdapter)pen).Pen.Clone(); - skPaint.IsAntialias = _antiAlias; - return skPaint; - } - - #endregion - } + if (prevMode != null) + { + _antiAlias = (bool)prevMode; + } + } + + public override RSize MeasureString(string str, RFont font) + { + var fontAdapter = (FontAdapter)font; + var realFont = fontAdapter.Font; + var p = new SKPaint(realFont); + var boundingRect = new SKRect(); + var measuredWidth = p.MeasureText(str, ref boundingRect); + + if (font.Height < 0) + { + var height = realFont.Metrics.XMax + realFont.Metrics.XMin; + var descent = realFont.Metrics.Descent; + fontAdapter.SetMetrics((int)Math.Round(height, MidpointRounding.AwayFromZero), (int)Math.Round((height - descent + 1f), MidpointRounding.AwayFromZero)); + } + + return new RSize(measuredWidth, boundingRect.Height); + } + + public override void MeasureString(string str, RFont font, double maxWidth, out int charFit, out double charFitWidth) + { + // there is no need for it - used for text selection + throw new NotSupportedException(); + } + + public override void DrawString(string str, RFont font, RColor color, RPoint point, RSize size, bool rtl) + { + //var xBrush = ((BrushAdapter)_adapter.GetSolidBrush(color)).Brush; + var skiaFont = ((FontAdapter)font).Font; + var p = new SKPaint + { + IsAntialias = _antiAlias, + FilterQuality = SKFilterQuality.Medium, + Color = Utils.Convert(color) + }; + _g.DrawText(str, (float)point.X, (float)point.Y - skiaFont.Metrics.Ascent, skiaFont, p); + } + + public override RBrush GetTextureBrush(RImage image, RRect dstRect, RPoint translateTransformLocation) + { + return new BrushAdapter(new XTextureBrush(((ImageAdapter)image).Image, Utils.Convert(dstRect), Utils.Convert(translateTransformLocation))); + } + + public override RGraphicsPath GetGraphicsPath() + { + return new GraphicsPathAdapter(); + } + + public override void Dispose() + { + if (_releaseGraphics) + _g.Dispose(); + } + + + #region Delegate graphics methods + + public override void DrawLine(RPen pen, double x1, double y1, double x2, double y2) + { + _g.DrawLine((float)x1, (float)y1, (float)x2, (float)y2, GetPaint(pen)); + } + + public override void DrawRectangle(RPen pen, double x, double y, double width, double height) + { + _g.DrawRect((float)x, (float)y, (float)width, (float)height, GetPaint(pen)); + } + + public override void DrawRectangle(RBrush brush, double x, double y, double width, double height) + { + var untypedBrush = ((BrushAdapter)brush).Brush; + if (untypedBrush is XTextureBrush textureBrush) + { + textureBrush.DrawRectangle(_g, (float)x, (float)y, (float)width, (float)height); + } + else if (untypedBrush is SKBrush skBrush) + { + var p = skBrush.GetPaint().Clone(); + p.IsAntialias = _antiAlias; + _g.DrawRect((float)x, (float)y, (float)width, (float)height, p); + } + } + + public override void DrawImage(RImage image, RRect destRect, RRect srcRect) + { + ((ImageAdapter)image).DrawImage(_g, Utils.Convert(destRect), Utils.Convert(srcRect)); + } + + public override void DrawImage(RImage image, RRect destRect) + { + ((ImageAdapter)image).DrawImage(_g, Utils.Convert(destRect)); + } + + public override void DrawPath(RPen pen, RGraphicsPath path) + { + _g.DrawPath(((GraphicsPathAdapter)path).GraphicsPath, GetPaint(pen)); + } + + public override void DrawPath(RBrush brush, RGraphicsPath path) + { + _g.DrawPath(((GraphicsPathAdapter)path).GraphicsPath, GetPaint(brush)); + } + + public override void DrawPolygon(RBrush brush, RPoint[] points) + { + var p = GetPaint(brush); + + if (points != null && points.Length > 0) + { + //(XBrush)((BrushAdapter)brush).Brush + var path = new SKPath(); + path.AddPoly(Utils.Convert(points)); + _g.DrawPath(path, p); + } + } + + private SKPaint GetPaint(RBrush brush) + { + SKBrush skBrush = (SKBrush)((BrushAdapter)brush).Brush; + var p = skBrush.GetPaint().Clone(); + p.IsAntialias = _antiAlias; + return p; + } + + private SKPaint GetPaint(RPen pen) + { + var skPaint = ((PenAdapter)pen).Pen.Clone(); + skPaint.IsAntialias = _antiAlias; + return skPaint; + } + + #endregion + } } \ No newline at end of file From d99d3cfd54207453e7990d39837809c4d52550a1 Mon Sep 17 00:00:00 2001 From: Alby Blyth Date: Thu, 25 Jan 2024 14:33:49 +1000 Subject: [PATCH 2/2] Update skia sharp adapter to use font manager default singleton --- Source/HtmlRenderer.SkiaSharp/Adapters/SkiaSharpAdapter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/HtmlRenderer.SkiaSharp/Adapters/SkiaSharpAdapter.cs b/Source/HtmlRenderer.SkiaSharp/Adapters/SkiaSharpAdapter.cs index 85ee85f22..4b6951f03 100644 --- a/Source/HtmlRenderer.SkiaSharp/Adapters/SkiaSharpAdapter.cs +++ b/Source/HtmlRenderer.SkiaSharp/Adapters/SkiaSharpAdapter.cs @@ -43,7 +43,7 @@ private SkiaSharpAdapter() AddFontFamilyMapping("monospace", "Courier New"); AddFontFamilyMapping("Helvetica", "Arial"); - var manager = SKFontManager.CreateDefault(); + var manager = SKFontManager.Default; var families = manager.GetFontFamilies(); foreach (var family in families)