From 230e47991f786bc579821b31cf1e0a4689a8befa Mon Sep 17 00:00:00 2001 From: Scott Williams Date: Tue, 30 May 2017 22:54:04 +0100 Subject: [PATCH 1/4] migrate text glyph rendering to SixLabors.Shapes.Text --- .../ImageSharp.Drawing.csproj | 3 +- .../Paths/DrawPathCollection.cs | 115 ++++++++++++++++ .../Paths/FillPathCollection.cs | 81 +++++++++++ src/ImageSharp.Drawing/Text/DrawText.cs | 26 ++-- src/ImageSharp.Drawing/Text/GlyphBuilder.cs | 127 ------------------ .../Text/TextGraphicsOptions.cs | 13 +- .../Drawing/Text/GlyphBuilder.cs | 68 ---------- 7 files changed, 215 insertions(+), 218 deletions(-) create mode 100644 src/ImageSharp.Drawing/Paths/DrawPathCollection.cs create mode 100644 src/ImageSharp.Drawing/Paths/FillPathCollection.cs delete mode 100644 src/ImageSharp.Drawing/Text/GlyphBuilder.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/Text/GlyphBuilder.cs diff --git a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj index a3552a09c..a9afe37f8 100644 --- a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj +++ b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj @@ -36,11 +36,10 @@ + All - - ..\..\ImageSharp.ruleset diff --git a/src/ImageSharp.Drawing/Paths/DrawPathCollection.cs b/src/ImageSharp.Drawing/Paths/DrawPathCollection.cs new file mode 100644 index 000000000..5cb499415 --- /dev/null +++ b/src/ImageSharp.Drawing/Paths/DrawPathCollection.cs @@ -0,0 +1,115 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp +{ + using Drawing; + using Drawing.Brushes; + using Drawing.Pens; + using ImageSharp.PixelFormats; + using SixLabors.Shapes; + + /// + /// Extension methods for the type. + /// + public static partial class ImageExtensions + { + /// + /// Draws the outline of the polygon with the provided pen. + /// + /// The type of the color. + /// The image this method extends. + /// The pen. + /// The paths. + /// The options. + /// The . + public static Image Draw(this Image source, IPen pen, IPathCollection paths, GraphicsOptions options) + where TPixel : struct, IPixel + { + foreach (IPath path in paths) + { + source.Draw(pen, new ShapePath(path), options); + } + + return source; + } + + /// + /// Draws the outline of the polygon with the provided pen. + /// + /// The type of the color. + /// The image this method extends. + /// The pen. + /// The paths. + /// The . + public static Image Draw(this Image source, IPen pen, IPathCollection paths) + where TPixel : struct, IPixel + { + return source.Draw(pen, paths, GraphicsOptions.Default); + } + + /// + /// Draws the outline of the polygon with the provided brush at the provided thickness. + /// + /// The type of the color. + /// The image this method extends. + /// The brush. + /// The thickness. + /// The shapes. + /// The options. + /// The . + public static Image Draw(this Image source, IBrush brush, float thickness, IPathCollection paths, GraphicsOptions options) + where TPixel : struct, IPixel + { + return source.Draw(new Pen(brush, thickness), paths, options); + } + + /// + /// Draws the outline of the polygon with the provided brush at the provided thickness. + /// + /// The type of the color. + /// The image this method extends. + /// The brush. + /// The thickness. + /// The paths. + /// The . + public static Image Draw(this Image source, IBrush brush, float thickness, IPathCollection paths) + where TPixel : struct, IPixel + { + return source.Draw(new Pen(brush, thickness), paths); + } + + /// + /// Draws the outline of the polygon with the provided brush at the provided thickness. + /// + /// The type of the color. + /// The image this method extends. + /// The color. + /// The thickness. + /// The paths. + /// The options. + /// The . + public static Image Draw(this Image source, TPixel color, float thickness, IPathCollection paths, GraphicsOptions options) + where TPixel : struct, IPixel + { + return source.Draw(new SolidBrush(color), thickness, paths, options); + } + + /// + /// Draws the outline of the polygon with the provided brush at the provided thickness. + /// + /// The type of the color. + /// The image this method extends. + /// The color. + /// The thickness. + /// The paths. + /// The . + public static Image Draw(this Image source, TPixel color, float thickness, IPathCollection paths) + where TPixel : struct, IPixel + { + return source.Draw(new SolidBrush(color), thickness, paths); + } + } +} diff --git a/src/ImageSharp.Drawing/Paths/FillPathCollection.cs b/src/ImageSharp.Drawing/Paths/FillPathCollection.cs new file mode 100644 index 000000000..3ea9fb94b --- /dev/null +++ b/src/ImageSharp.Drawing/Paths/FillPathCollection.cs @@ -0,0 +1,81 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp +{ + using Drawing; + using Drawing.Brushes; + using ImageSharp.PixelFormats; + using SixLabors.Shapes; + + /// + /// Extension methods for the type. + /// + public static partial class ImageExtensions + { + /// + /// Flood fills the image in the shape of the provided polygon with the specified brush.. + /// + /// The type of the color. + /// The image this method extends. + /// The brush. + /// The shapes. + /// The graphics options. + /// The . + public static Image Fill(this Image source, IBrush brush, IPathCollection paths, GraphicsOptions options) + where TPixel : struct, IPixel + { + foreach (IPath s in paths) + { + source.Fill(brush, s, options); + } + + return source; + } + + /// + /// Flood fills the image in the shape of the provided polygon with the specified brush. + /// + /// The type of the color. + /// The image this method extends. + /// The brush. + /// The paths. + /// The . + public static Image Fill(this Image source, IBrush brush, IPathCollection paths) + where TPixel : struct, IPixel + { + return source.Fill(brush, paths, GraphicsOptions.Default); + } + + /// + /// Flood fills the image in the shape of the provided polygon with the specified brush.. + /// + /// The type of the color. + /// The image this method extends. + /// The color. + /// The paths. + /// The options. + /// The . + public static Image Fill(this Image source, TPixel color, IPathCollection paths, GraphicsOptions options) + where TPixel : struct, IPixel + { + return source.Fill(new SolidBrush(color), paths, options); + } + + /// + /// Flood fills the image in the shape of the provided polygon with the specified brush.. + /// + /// The type of the color. + /// The image this method extends. + /// The color. + /// The paths. + /// The . + public static Image Fill(this Image source, TPixel color, IPathCollection paths) + where TPixel : struct, IPixel + { + return source.Fill(new SolidBrush(color), paths); + } + } +} diff --git a/src/ImageSharp.Drawing/Text/DrawText.cs b/src/ImageSharp.Drawing/Text/DrawText.cs index bd33289fa..6bb87dcf5 100644 --- a/src/ImageSharp.Drawing/Text/DrawText.cs +++ b/src/ImageSharp.Drawing/Text/DrawText.cs @@ -12,6 +12,7 @@ namespace ImageSharp using Drawing.Pens; using ImageSharp.PixelFormats; using SixLabors.Fonts; + using SixLabors.Shapes; /// /// Extension methods for the type. @@ -167,43 +168,32 @@ namespace ImageSharp public static Image DrawText(this Image source, string text, Font font, IBrush brush, IPen pen, Vector2 location, TextGraphicsOptions options) where TPixel : struct, IPixel { - GlyphBuilder glyphBuilder = new GlyphBuilder(location); - - TextRenderer renderer = new TextRenderer(glyphBuilder); - Vector2 dpi = DefaultTextDpi; if (options.UseImageResolution) { dpi = new Vector2((float)source.MetaData.HorizontalResolution, (float)source.MetaData.VerticalResolution); } - FontSpan style = new FontSpan(font, dpi) + var style = new FontSpan(font, dpi) { ApplyKerning = options.ApplyKerning, TabWidth = options.TabWidth, WrappingWidth = options.WrapTextWidth, - Alignment = options.TextAlignment + HorizontalAlignment = options.HorizontalAlignment, + VerticalAlignment = options.VerticalAlignment }; - renderer.RenderText(text, style); - - System.Collections.Generic.IEnumerable shapesToDraw = glyphBuilder.Paths; + IPathCollection glyphs = TextBuilder.GenerateGlyphs(text, style).Translate(location); // todo move to better API - GraphicsOptions pathOptions = (GraphicsOptions)options; + var pathOptions = (GraphicsOptions)options; if (brush != null) { - foreach (SixLabors.Shapes.IPath s in shapesToDraw) - { - source.Fill(brush, s, pathOptions); - } + source.Fill(brush, glyphs, pathOptions); } if (pen != null) { - foreach (SixLabors.Shapes.IPath s in shapesToDraw) - { - source.Draw(pen, s, pathOptions); - } + source.Draw(pen, glyphs, pathOptions); } return source; diff --git a/src/ImageSharp.Drawing/Text/GlyphBuilder.cs b/src/ImageSharp.Drawing/Text/GlyphBuilder.cs deleted file mode 100644 index 0033a608c..000000000 --- a/src/ImageSharp.Drawing/Text/GlyphBuilder.cs +++ /dev/null @@ -1,127 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Drawing -{ - using System.Collections.Generic; - using System.Numerics; - - using SixLabors.Fonts; - using SixLabors.Shapes; - - /// - /// rendering surface that Fonts can use to generate Shapes. - /// - internal class GlyphBuilder : IGlyphRenderer - { - private readonly PathBuilder builder = new PathBuilder(); - private readonly List paths = new List(); - private Vector2 currentPoint = default(Vector2); - - /// - /// Initializes a new instance of the class. - /// - public GlyphBuilder() - : this(Vector2.Zero) - { - // glyphs are renderd realative to bottom left so invert the Y axis to allow it to render on top left origin surface - this.builder = new PathBuilder(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The origin. - public GlyphBuilder(Vector2 origin) - { - this.builder = new PathBuilder(); - this.builder.SetOrigin(origin); - } - - /// - /// Gets the paths that have been rendered by this. - /// - public IEnumerable Paths => this.paths; - - /// - /// Begins the glyph. - /// - /// The offset that the glyph will be rendered at. - void IGlyphRenderer.BeginGlyph(Vector2 location) - { - this.builder.Clear(); - } - - /// - /// Begins the figure. - /// - void IGlyphRenderer.BeginFigure() - { - this.builder.StartFigure(); - } - - /// - /// Draws a cubic bezier from the current point to the - /// - /// The second control point. - /// The third control point. - /// The point. - void IGlyphRenderer.CubicBezierTo(Vector2 secondControlPoint, Vector2 thirdControlPoint, Vector2 point) - { - this.builder.AddBezier(this.currentPoint, secondControlPoint, thirdControlPoint, point); - this.currentPoint = point; - } - - /// - /// Ends the glyph. - /// - void IGlyphRenderer.EndGlyph() - { - this.paths.Add(this.builder.Build()); - } - - /// - /// Ends the figure. - /// - void IGlyphRenderer.EndFigure() - { - this.builder.CloseFigure(); - } - - /// - /// Draws a line from the current point to the . - /// - /// The point. - void IGlyphRenderer.LineTo(Vector2 point) - { - this.builder.AddLine(this.currentPoint, point); - this.currentPoint = point; - } - - /// - /// Moves to current point to the supplied vector. - /// - /// The point. - void IGlyphRenderer.MoveTo(Vector2 point) - { - this.builder.StartFigure(); - this.currentPoint = point; - } - - /// - /// Draws a quadratics bezier from the current point to the - /// - /// The second control point. - /// The point. - void IGlyphRenderer.QuadraticBezierTo(Vector2 secondControlPoint, Vector2 point) - { - Vector2 c1 = (((secondControlPoint - this.currentPoint) * 2) / 3) + this.currentPoint; - Vector2 c2 = (((secondControlPoint - point) * 2) / 3) + point; - - this.builder.AddBezier(this.currentPoint, c1, c2, point); - this.currentPoint = point; - } - } -} diff --git a/src/ImageSharp.Drawing/Text/TextGraphicsOptions.cs b/src/ImageSharp.Drawing/Text/TextGraphicsOptions.cs index 388b39bcc..593ac36d4 100644 --- a/src/ImageSharp.Drawing/Text/TextGraphicsOptions.cs +++ b/src/ImageSharp.Drawing/Text/TextGraphicsOptions.cs @@ -33,7 +33,8 @@ namespace ImageSharp.Drawing private float wrapTextWidth; - private SixLabors.Fonts.TextAlignment? textAlignment; + private SixLabors.Fonts.HorizontalAlignment? horizontalAlignment; + private SixLabors.Fonts.VerticalAlignment? verticalAlignment; /// /// Initializes a new instance of the struct. @@ -45,7 +46,8 @@ namespace ImageSharp.Drawing this.tabWidth = 4; this.useImageResolution = false; this.wrapTextWidth = 0; - this.textAlignment = SixLabors.Fonts.TextAlignment.Left; + this.horizontalAlignment = HorizontalAlignment.Left; + this.verticalAlignment = VerticalAlignment.Top; this.antialiasSubpixelDepth = 16; this.blenderMode = PixelBlenderMode.Normal; @@ -104,7 +106,12 @@ namespace ImageSharp.Drawing /// defined by the location and width, if equals zero, and thus /// wrapping disabled, then the alignment is relative to the drawing location. /// - public TextAlignment TextAlignment { get => this.textAlignment ?? TextAlignment.Left; set => this.textAlignment = value; } + public HorizontalAlignment HorizontalAlignment { get => this.horizontalAlignment ?? HorizontalAlignment.Left; set => this.horizontalAlignment = value; } + + /// + /// Gets or sets a value indicating how to align the text relative to the rendering space. + /// + public VerticalAlignment VerticalAlignment { get => this.verticalAlignment ?? VerticalAlignment.Top; set => this.verticalAlignment = value; } /// /// Performs an implicit conversion from to . diff --git a/tests/ImageSharp.Tests/Drawing/Text/GlyphBuilder.cs b/tests/ImageSharp.Tests/Drawing/Text/GlyphBuilder.cs deleted file mode 100644 index 7f16f30bb..000000000 --- a/tests/ImageSharp.Tests/Drawing/Text/GlyphBuilder.cs +++ /dev/null @@ -1,68 +0,0 @@ - -namespace ImageSharp.Tests.Drawing.Text -{ - using ImageSharp.Drawing; - using SixLabors.Fonts; - using System; - using System.Collections.Generic; - using System.Linq; - using System.Numerics; - using System.Threading.Tasks; - using Xunit; - - public class GlyphBuilderTests - { - [Fact] - public void OriginUsed() - { - // Y axis is inverted as it expects to be drawing for bottom left - GlyphBuilder fullBuilder = new GlyphBuilder(new System.Numerics.Vector2(10, 99)); - IGlyphRenderer builder = fullBuilder; - - builder.BeginGlyph(Vector2.Zero); - builder.BeginFigure(); - builder.MoveTo(new Vector2(0, 0)); - builder.LineTo(new Vector2(0, 10)); // becomes 0, -10 - - builder.CubicBezierTo( - new Vector2(15, 15), // control point - will not be in the final point collection - new Vector2(15, 10), // control point - will not be in the final point collection - new Vector2(10, 10));// becomes 10, -10 - - builder.QuadraticBezierTo( - new Vector2(10, 5), // control point - will not be in the final point collection - new Vector2(10, 0)); - - builder.EndFigure(); - builder.EndGlyph(); - - System.Collections.Immutable.ImmutableArray points = fullBuilder.Paths.Single().Flatten().Single().Points; - - Assert.Contains(new Vector2(10, 99), points); - Assert.Contains(new Vector2(10, 109), points); - Assert.Contains(new Vector2(20, 99), points); - Assert.Contains(new Vector2(20, 109), points); - } - - [Fact] - public void EachGlypeCausesNewPath() - { - // Y axis is inverted as it expects to be drawing for bottom left - GlyphBuilder fullBuilder = new GlyphBuilder(); - IGlyphRenderer builder = fullBuilder; - for (int i = 0; i < 10; i++) - { - builder.BeginGlyph(Vector2.Zero); - builder.BeginFigure(); - builder.MoveTo(new Vector2(0, 0)); - builder.LineTo(new Vector2(0, 10)); // becomes 0, -10 - builder.LineTo(new Vector2(10, 10));// becomes 10, -10 - builder.LineTo(new Vector2(10, 0)); - builder.EndFigure(); - builder.EndGlyph(); - } - - Assert.Equal(10, fullBuilder.Paths.Count()); - } - } -} From 8e6aecbd0b31309d75a6de5410756b345eb3293a Mon Sep 17 00:00:00 2001 From: Scott Williams Date: Wed, 31 May 2017 19:30:09 +0100 Subject: [PATCH 2/4] add unit tests --- .../Drawing/Paths/DrawPathCollection.cs | 179 ++++++++++++++++++ .../Drawing/Paths/FillPathCollection.cs | 131 +++++++++++++ 2 files changed, 310 insertions(+) create mode 100644 tests/ImageSharp.Tests/Drawing/Paths/DrawPathCollection.cs create mode 100644 tests/ImageSharp.Tests/Drawing/Paths/FillPathCollection.cs diff --git a/tests/ImageSharp.Tests/Drawing/Paths/DrawPathCollection.cs b/tests/ImageSharp.Tests/Drawing/Paths/DrawPathCollection.cs new file mode 100644 index 000000000..5148236d8 --- /dev/null +++ b/tests/ImageSharp.Tests/Drawing/Paths/DrawPathCollection.cs @@ -0,0 +1,179 @@ + +namespace ImageSharp.Tests.Drawing.Paths +{ + using System; + + using ImageSharp.Drawing.Brushes; + + using Xunit; + using ImageSharp.Drawing; + using System.Numerics; + using SixLabors.Shapes; + using ImageSharp.Drawing.Processors; + using ImageSharp.Drawing.Pens; + using ImageSharp.PixelFormats; + + public class DrawPathCollection : IDisposable + { + float thickness = 7.2f; + GraphicsOptions noneDefault = new GraphicsOptions(); + Rgba32 color = Rgba32.HotPink; + SolidBrush brush = Brushes.Solid(Rgba32.HotPink); + Pen pen = new Pen(Rgba32.Gray, 99.9f); + IPath path1 = new SixLabors.Shapes.Path(new LinearLineSegment(new Vector2[] { + new Vector2(10,10), + new Vector2(20,10), + new Vector2(20,10), + new Vector2(30,10), + })); + + IPath path2 = new SixLabors.Shapes.Path(new LinearLineSegment(new Vector2[] { + new Vector2(10,10), + new Vector2(20,10), + new Vector2(20,10), + new Vector2(30,10), + })); + + IPathCollection pathCollection; + private ProcessorWatchingImage img; + + public DrawPathCollection() + { + this.pathCollection = new PathCollection(this.path1, this.path2); + this.img = new Paths.ProcessorWatchingImage(10, 10); + } + + public void Dispose() + { + img.Dispose(); + } + + [Fact] + public void CorrectlySetsBrushThicknessAndPath() + { + img.Draw(brush, thickness, pathCollection); + + Assert.NotEmpty(img.ProcessorApplications); + + for (var i = 0; i < 2; i++) + { + DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[i].processor); + + Assert.Equal(GraphicsOptions.Default, processor.Options); + + ShapePath shapepath = Assert.IsType(processor.Path); + Assert.Contains(shapepath.Path, this.pathCollection); + + Pen pen = Assert.IsType>(processor.Pen); + Assert.Equal(brush, pen.Brush); + Assert.Equal(thickness, pen.Width); + } + } + + [Fact] + public void CorrectlySetsBrushThicknessPathAndOptions() + { + img.Draw(brush, thickness, pathCollection, noneDefault); + + Assert.NotEmpty(img.ProcessorApplications); + + for (var i = 0; i < 2; i++) + { + DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[i].processor); + + Assert.Equal(noneDefault, processor.Options); + + ShapePath shapepath = Assert.IsType(processor.Path); + Assert.Contains(shapepath.Path, pathCollection); + + Pen pen = Assert.IsType>(processor.Pen); + Assert.Equal(brush, pen.Brush); + Assert.Equal(thickness, pen.Width); + } + } + + [Fact] + public void CorrectlySetsColorThicknessAndPath() + { + img.Draw(color, thickness, pathCollection); + + Assert.NotEmpty(img.ProcessorApplications); + for (var i = 0; i < 2; i++) + { + DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[i].processor); + + Assert.Equal(GraphicsOptions.Default, processor.Options); + + ShapePath shapepath = Assert.IsType(processor.Path); + Assert.Contains(shapepath.Path, pathCollection); + + Pen pen = Assert.IsType>(processor.Pen); + Assert.Equal(thickness, pen.Width); + + SolidBrush brush = Assert.IsType>(pen.Brush); + Assert.Equal(color, brush.Color); + } + } + + [Fact] + public void CorrectlySetsColorThicknessPathAndOptions() + { + img.Draw(color, thickness, pathCollection, noneDefault); + + Assert.Equal(2, img.ProcessorApplications.Count); + for (var i = 0; i < 2; i++) + { + DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[i].processor); + + Assert.Equal(noneDefault, processor.Options); + + ShapePath shapepath = Assert.IsType(processor.Path); + Assert.Contains(shapepath.Path, pathCollection); + + Pen pen = Assert.IsType>(processor.Pen); + Assert.Equal(thickness, pen.Width); + + SolidBrush brush = Assert.IsType>(pen.Brush); + Assert.Equal(color, brush.Color); + } + } + + [Fact] + public void CorrectlySetsPenAndPath() + { + img.Draw(pen, pathCollection); + + Assert.Equal(2, img.ProcessorApplications.Count); + for (var i = 0; i < 2; i++) + { + DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[i].processor); + + Assert.Equal(GraphicsOptions.Default, processor.Options); + + ShapePath shapepath = Assert.IsType(processor.Path); + Assert.Contains(shapepath.Path, pathCollection); + + Assert.Equal(pen, processor.Pen); + } + } + + [Fact] + public void CorrectlySetsPenPathAndOptions() + { + img.Draw(pen, pathCollection, noneDefault); + + Assert.Equal(2, img.ProcessorApplications.Count); + for (var i = 0; i < 2; i++) + { + DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[i].processor); + + Assert.Equal(noneDefault, processor.Options); + + ShapePath shapepath = Assert.IsType(processor.Path); + Assert.Contains(shapepath.Path, pathCollection); + + Assert.Equal(pen, processor.Pen); + } + } + } +} diff --git a/tests/ImageSharp.Tests/Drawing/Paths/FillPathCollection.cs b/tests/ImageSharp.Tests/Drawing/Paths/FillPathCollection.cs new file mode 100644 index 000000000..e60ac0c13 --- /dev/null +++ b/tests/ImageSharp.Tests/Drawing/Paths/FillPathCollection.cs @@ -0,0 +1,131 @@ + +namespace ImageSharp.Tests.Drawing.Paths +{ + using System; + using ImageSharp; + using ImageSharp.Drawing.Brushes; + using Xunit; + using ImageSharp.Drawing; + using System.Numerics; + using SixLabors.Shapes; + using ImageSharp.Drawing.Processors; + using ImageSharp.PixelFormats; + + public class FillPathCollection : IDisposable + { + GraphicsOptions noneDefault = new GraphicsOptions(); + Rgba32 color = Rgba32.HotPink; + SolidBrush brush = Brushes.Solid(Rgba32.HotPink); + IPath path1 = new SixLabors.Shapes.Path(new LinearLineSegment(new Vector2[] { + new Vector2(10,10), + new Vector2(20,10), + new Vector2(20,10), + new Vector2(30,10), + })); + IPath path2 = new SixLabors.Shapes.Path(new LinearLineSegment(new Vector2[] { + new Vector2(10,10), + new Vector2(20,10), + new Vector2(20,10), + new Vector2(30,10), + })); + + IPathCollection pathCollection; + + private ProcessorWatchingImage img; + + public FillPathCollection() + { + this.pathCollection = new PathCollection(path1, path2); + this.img = new ProcessorWatchingImage(10, 10); + } + + public void Dispose() + { + img.Dispose(); + } + + [Fact] + public void CorrectlySetsBrushAndPath() + { + img.Fill(brush, pathCollection); + + Assert.Equal(2, img.ProcessorApplications.Count); + for (var i = 0; i < 2; i++) + { + FillRegionProcessor processor = Assert.IsType>(img.ProcessorApplications[i].processor); + + Assert.Equal(GraphicsOptions.Default, processor.Options); + + ShapeRegion region = Assert.IsType(processor.Region); + + // path is converted to a polygon before filling + Polygon polygon = Assert.IsType(region.Shape); + LinearLineSegment segments = Assert.IsType(polygon.LineSegments[0]); + + Assert.Equal(brush, processor.Brush); + } + } + + [Fact] + public void CorrectlySetsBrushPathOptions() + { + img.Fill(brush, pathCollection, noneDefault); + + Assert.Equal(2, img.ProcessorApplications.Count); + for (var i = 0; i < 2; i++) + { + FillRegionProcessor processor = Assert.IsType>(img.ProcessorApplications[i].processor); + + Assert.Equal(noneDefault, processor.Options); + + ShapeRegion region = Assert.IsType(processor.Region); + Polygon polygon = Assert.IsType(region.Shape); + LinearLineSegment segments = Assert.IsType(polygon.LineSegments[0]); + + Assert.Equal(brush, processor.Brush); + } + } + + [Fact] + public void CorrectlySetsColorAndPath() + { + img.Fill(color, pathCollection); + + Assert.Equal(2, img.ProcessorApplications.Count); + for (var i = 0; i < 2; i++) + { + FillRegionProcessor processor = Assert.IsType>(img.ProcessorApplications[i].processor); + + Assert.Equal(GraphicsOptions.Default, processor.Options); + + ShapeRegion region = Assert.IsType(processor.Region); + Polygon polygon = Assert.IsType(region.Shape); + LinearLineSegment segments = Assert.IsType(polygon.LineSegments[0]); + + SolidBrush brush = Assert.IsType>(processor.Brush); + Assert.Equal(color, brush.Color); + } + } + + [Fact] + public void CorrectlySetsColorPathAndOptions() + { + img.Fill(color, pathCollection, noneDefault); + + Assert.Equal(2, img.ProcessorApplications.Count); + for (var i = 0; i < 2; i++) + { + FillRegionProcessor processor = Assert.IsType>(img.ProcessorApplications[i].processor); + + Assert.Equal(noneDefault, processor.Options); + + ShapeRegion region = Assert.IsType(processor.Region); + Polygon polygon = Assert.IsType(region.Shape); + LinearLineSegment segments = Assert.IsType(polygon.LineSegments[0]); + + SolidBrush brush = Assert.IsType>(processor.Brush); + Assert.Equal(color, brush.Color); + } + } + } +} From 7c81b0cc356297c8dfcad436af3830f9eeab7ad9 Mon Sep 17 00:00:00 2001 From: Scott Williams Date: Wed, 31 May 2017 20:45:29 +0100 Subject: [PATCH 3/4] add draw text along path extension methods --- .../ImageSharp.Drawing.csproj | 2 +- .../Paths/DrawPathCollection.cs | 2 +- src/ImageSharp.Drawing/Text/DrawText.Path.cs | 200 ++++++++++++++ src/ImageSharp.Drawing/Text/DrawText.cs | 2 +- .../Drawing/Paths/DrawPathCollection.cs | 179 ------------- .../Drawing/Text/DrawText.Path.cs | 251 ++++++++++++++++++ 6 files changed, 454 insertions(+), 182 deletions(-) create mode 100644 src/ImageSharp.Drawing/Text/DrawText.Path.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/Paths/DrawPathCollection.cs create mode 100644 tests/ImageSharp.Tests/Drawing/Text/DrawText.Path.cs diff --git a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj index a9afe37f8..9d24c1777 100644 --- a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj +++ b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj @@ -36,7 +36,7 @@ - + All diff --git a/src/ImageSharp.Drawing/Paths/DrawPathCollection.cs b/src/ImageSharp.Drawing/Paths/DrawPathCollection.cs index 5cb499415..877737653 100644 --- a/src/ImageSharp.Drawing/Paths/DrawPathCollection.cs +++ b/src/ImageSharp.Drawing/Paths/DrawPathCollection.cs @@ -30,7 +30,7 @@ namespace ImageSharp { foreach (IPath path in paths) { - source.Draw(pen, new ShapePath(path), options); + source.Draw(pen, path, options); } return source; diff --git a/src/ImageSharp.Drawing/Text/DrawText.Path.cs b/src/ImageSharp.Drawing/Text/DrawText.Path.cs new file mode 100644 index 000000000..2bc23b64b --- /dev/null +++ b/src/ImageSharp.Drawing/Text/DrawText.Path.cs @@ -0,0 +1,200 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp +{ + using System.Numerics; + + using Drawing; + using Drawing.Brushes; + using Drawing.Pens; + using ImageSharp.PixelFormats; + using SixLabors.Fonts; + using SixLabors.Shapes; + + /// + /// Extension methods for the type. + /// + public static partial class ImageExtensions + { + /// + /// Draws the text onto the the image filled via the brush. + /// + /// The type of the color. + /// The image this method extends. + /// The text. + /// The font. + /// The color. + /// The path. + /// + /// The . + /// + public static Image DrawText(this Image source, string text, Font font, TPixel color, IPath path) + where TPixel : struct, IPixel + { + return source.DrawText(text, font, color, path, TextGraphicsOptions.Default); + } + + /// + /// Draws the text onto the the image filled via the brush. + /// + /// The type of the color. + /// The image this method extends. + /// The text. + /// The font. + /// The color. + /// The path. + /// The options. + /// + /// The . + /// + public static Image DrawText(this Image source, string text, Font font, TPixel color, IPath path, TextGraphicsOptions options) + where TPixel : struct, IPixel + { + return source.DrawText(text, font, Brushes.Solid(color), null, path, options); + } + + /// + /// Draws the text onto the the image filled via the brush. + /// + /// The type of the color. + /// The image this method extends. + /// The text. + /// The font. + /// The brush. + /// The location. + /// + /// The . + /// + public static Image DrawText(this Image source, string text, Font font, IBrush brush, IPath path) + where TPixel : struct, IPixel + { + return source.DrawText(text, font, brush, path, TextGraphicsOptions.Default); + } + + /// + /// Draws the text onto the the image filled via the brush. + /// + /// The type of the color. + /// The image this method extends. + /// The text. + /// The font. + /// The brush. + /// The path. + /// The options. + /// + /// The . + /// + public static Image DrawText(this Image source, string text, Font font, IBrush brush, IPath path, TextGraphicsOptions options) + where TPixel : struct, IPixel + { + return source.DrawText(text, font, brush, null, path, options); + } + + /// + /// Draws the text onto the the image outlined via the pen. + /// + /// The type of the color. + /// The image this method extends. + /// The text. + /// The font. + /// The pen. + /// The path. + /// + /// The . + /// + public static Image DrawText(this Image source, string text, Font font, IPen pen, IPath path) + where TPixel : struct, IPixel + { + return source.DrawText(text, font, pen, path, TextGraphicsOptions.Default); + } + + /// + /// Draws the text onto the the image outlined via the pen. + /// + /// The type of the color. + /// The image this method extends. + /// The text. + /// The font. + /// The pen. + /// The path. + /// The options. + /// + /// The . + /// + public static Image DrawText(this Image source, string text, Font font, IPen pen, IPath path, TextGraphicsOptions options) + where TPixel : struct, IPixel + { + return source.DrawText(text, font, null, pen, path, options); + } + + /// + /// Draws the text onto the the image filled via the brush then outlined via the pen. + /// + /// The type of the color. + /// The image this method extends. + /// The text. + /// The font. + /// The brush. + /// The pen. + /// The path. + /// + /// The . + /// + public static Image DrawText(this Image source, string text, Font font, IBrush brush, IPen pen, IPath path) + where TPixel : struct, IPixel + { + return source.DrawText(text, font, brush, pen, path, TextGraphicsOptions.Default); + } + + /// + /// Draws the text onto the the image filled via the brush then outlined via the pen. + /// + /// The type of the color. + /// The image this method extends. + /// The text. + /// The font. + /// The brush. + /// The pen. + /// The path. + /// The options. + /// + /// The . + /// + public static Image DrawText(this Image source, string text, Font font, IBrush brush, IPen pen, IPath path, TextGraphicsOptions options) + where TPixel : struct, IPixel + { + Vector2 dpi = DefaultTextDpi; + if (options.UseImageResolution) + { + dpi = new Vector2((float)source.MetaData.HorizontalResolution, (float)source.MetaData.VerticalResolution); + } + + var style = new FontSpan(font, dpi) + { + ApplyKerning = options.ApplyKerning, + TabWidth = options.TabWidth, + WrappingWidth = options.WrapTextWidth, + HorizontalAlignment = options.HorizontalAlignment, + VerticalAlignment = options.VerticalAlignment + }; + + IPathCollection glyphs = TextBuilder.GenerateGlyphs(text, path, style); + + var pathOptions = (GraphicsOptions)options; + if (brush != null) + { + source.Fill(brush, glyphs, pathOptions); + } + + if (pen != null) + { + source.Draw(pen, glyphs, pathOptions); + } + + return source; + } + } +} diff --git a/src/ImageSharp.Drawing/Text/DrawText.cs b/src/ImageSharp.Drawing/Text/DrawText.cs index 6bb87dcf5..3b0d3db41 100644 --- a/src/ImageSharp.Drawing/Text/DrawText.cs +++ b/src/ImageSharp.Drawing/Text/DrawText.cs @@ -183,7 +183,7 @@ namespace ImageSharp VerticalAlignment = options.VerticalAlignment }; - IPathCollection glyphs = TextBuilder.GenerateGlyphs(text, style).Translate(location); // todo move to better API + IPathCollection glyphs = TextBuilder.GenerateGlyphs(text, location, style); var pathOptions = (GraphicsOptions)options; if (brush != null) diff --git a/tests/ImageSharp.Tests/Drawing/Paths/DrawPathCollection.cs b/tests/ImageSharp.Tests/Drawing/Paths/DrawPathCollection.cs deleted file mode 100644 index 5148236d8..000000000 --- a/tests/ImageSharp.Tests/Drawing/Paths/DrawPathCollection.cs +++ /dev/null @@ -1,179 +0,0 @@ - -namespace ImageSharp.Tests.Drawing.Paths -{ - using System; - - using ImageSharp.Drawing.Brushes; - - using Xunit; - using ImageSharp.Drawing; - using System.Numerics; - using SixLabors.Shapes; - using ImageSharp.Drawing.Processors; - using ImageSharp.Drawing.Pens; - using ImageSharp.PixelFormats; - - public class DrawPathCollection : IDisposable - { - float thickness = 7.2f; - GraphicsOptions noneDefault = new GraphicsOptions(); - Rgba32 color = Rgba32.HotPink; - SolidBrush brush = Brushes.Solid(Rgba32.HotPink); - Pen pen = new Pen(Rgba32.Gray, 99.9f); - IPath path1 = new SixLabors.Shapes.Path(new LinearLineSegment(new Vector2[] { - new Vector2(10,10), - new Vector2(20,10), - new Vector2(20,10), - new Vector2(30,10), - })); - - IPath path2 = new SixLabors.Shapes.Path(new LinearLineSegment(new Vector2[] { - new Vector2(10,10), - new Vector2(20,10), - new Vector2(20,10), - new Vector2(30,10), - })); - - IPathCollection pathCollection; - private ProcessorWatchingImage img; - - public DrawPathCollection() - { - this.pathCollection = new PathCollection(this.path1, this.path2); - this.img = new Paths.ProcessorWatchingImage(10, 10); - } - - public void Dispose() - { - img.Dispose(); - } - - [Fact] - public void CorrectlySetsBrushThicknessAndPath() - { - img.Draw(brush, thickness, pathCollection); - - Assert.NotEmpty(img.ProcessorApplications); - - for (var i = 0; i < 2; i++) - { - DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[i].processor); - - Assert.Equal(GraphicsOptions.Default, processor.Options); - - ShapePath shapepath = Assert.IsType(processor.Path); - Assert.Contains(shapepath.Path, this.pathCollection); - - Pen pen = Assert.IsType>(processor.Pen); - Assert.Equal(brush, pen.Brush); - Assert.Equal(thickness, pen.Width); - } - } - - [Fact] - public void CorrectlySetsBrushThicknessPathAndOptions() - { - img.Draw(brush, thickness, pathCollection, noneDefault); - - Assert.NotEmpty(img.ProcessorApplications); - - for (var i = 0; i < 2; i++) - { - DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[i].processor); - - Assert.Equal(noneDefault, processor.Options); - - ShapePath shapepath = Assert.IsType(processor.Path); - Assert.Contains(shapepath.Path, pathCollection); - - Pen pen = Assert.IsType>(processor.Pen); - Assert.Equal(brush, pen.Brush); - Assert.Equal(thickness, pen.Width); - } - } - - [Fact] - public void CorrectlySetsColorThicknessAndPath() - { - img.Draw(color, thickness, pathCollection); - - Assert.NotEmpty(img.ProcessorApplications); - for (var i = 0; i < 2; i++) - { - DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[i].processor); - - Assert.Equal(GraphicsOptions.Default, processor.Options); - - ShapePath shapepath = Assert.IsType(processor.Path); - Assert.Contains(shapepath.Path, pathCollection); - - Pen pen = Assert.IsType>(processor.Pen); - Assert.Equal(thickness, pen.Width); - - SolidBrush brush = Assert.IsType>(pen.Brush); - Assert.Equal(color, brush.Color); - } - } - - [Fact] - public void CorrectlySetsColorThicknessPathAndOptions() - { - img.Draw(color, thickness, pathCollection, noneDefault); - - Assert.Equal(2, img.ProcessorApplications.Count); - for (var i = 0; i < 2; i++) - { - DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[i].processor); - - Assert.Equal(noneDefault, processor.Options); - - ShapePath shapepath = Assert.IsType(processor.Path); - Assert.Contains(shapepath.Path, pathCollection); - - Pen pen = Assert.IsType>(processor.Pen); - Assert.Equal(thickness, pen.Width); - - SolidBrush brush = Assert.IsType>(pen.Brush); - Assert.Equal(color, brush.Color); - } - } - - [Fact] - public void CorrectlySetsPenAndPath() - { - img.Draw(pen, pathCollection); - - Assert.Equal(2, img.ProcessorApplications.Count); - for (var i = 0; i < 2; i++) - { - DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[i].processor); - - Assert.Equal(GraphicsOptions.Default, processor.Options); - - ShapePath shapepath = Assert.IsType(processor.Path); - Assert.Contains(shapepath.Path, pathCollection); - - Assert.Equal(pen, processor.Pen); - } - } - - [Fact] - public void CorrectlySetsPenPathAndOptions() - { - img.Draw(pen, pathCollection, noneDefault); - - Assert.Equal(2, img.ProcessorApplications.Count); - for (var i = 0; i < 2; i++) - { - DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[i].processor); - - Assert.Equal(noneDefault, processor.Options); - - ShapePath shapepath = Assert.IsType(processor.Path); - Assert.Contains(shapepath.Path, pathCollection); - - Assert.Equal(pen, processor.Pen); - } - } - } -} diff --git a/tests/ImageSharp.Tests/Drawing/Text/DrawText.Path.cs b/tests/ImageSharp.Tests/Drawing/Text/DrawText.Path.cs new file mode 100644 index 000000000..60fe44acd --- /dev/null +++ b/tests/ImageSharp.Tests/Drawing/Text/DrawText.Path.cs @@ -0,0 +1,251 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Tests.Drawing.Text +{ + using System; + using System.Numerics; + + using ImageSharp.Drawing; + using ImageSharp.Drawing.Brushes; + using ImageSharp.Drawing.Pens; + using ImageSharp.Drawing.Processors; + using ImageSharp.PixelFormats; + using ImageSharp.Tests.Drawing.Paths; + + using SixLabors.Fonts; + using SixLabors.Shapes; + + using Xunit; + + public class DrawText_Path : IDisposable + { + Rgba32 color = Rgba32.HotPink; + + SolidBrush brush = Brushes.Solid(Rgba32.HotPink); + + IPath path = new SixLabors.Shapes.Path( + new LinearLineSegment( + new Vector2[] { new Vector2(10, 10), new Vector2(20, 10), new Vector2(20, 10), new Vector2(30, 10), })); + + private ProcessorWatchingImage img; + + private readonly FontCollection FontCollection; + + private readonly Font Font; + + public DrawText_Path() + { + this.FontCollection = new FontCollection(); + this.Font = this.FontCollection.Install(TestFontUtilities.GetPath("SixLaborsSampleAB.woff")); + this.img = new ProcessorWatchingImage(10, 10); + } + + public void Dispose() + { + this.img.Dispose(); + } + + [Fact] + public void FillsForEachACharachterWhenBrushSetAndNotPen() + { + this.img.DrawText( + "123", + this.Font, + Brushes.Solid(Rgba32.Red), + null, + path, + new TextGraphicsOptions(true)); + + Assert.NotEmpty(this.img.ProcessorApplications); + Assert.Equal(3, this.img.ProcessorApplications.Count); // 3 fills where applied + Assert.IsType>(this.img.ProcessorApplications[0].processor); + } + + [Fact] + public void FillsForEachACharachterWhenBrushSetAndNotPenDefaultOptions() + { + this.img.DrawText("123", this.Font, Brushes.Solid(Rgba32.Red), null, path); + + Assert.NotEmpty(this.img.ProcessorApplications); + Assert.Equal(3, this.img.ProcessorApplications.Count); // 3 fills where applied + Assert.IsType>(this.img.ProcessorApplications[0].processor); + } + + [Fact] + public void FillsForEachACharachterWhenBrushSet() + { + this.img.DrawText("123", this.Font, Brushes.Solid(Rgba32.Red), path, new TextGraphicsOptions(true)); + + Assert.NotEmpty(this.img.ProcessorApplications); + Assert.Equal(3, this.img.ProcessorApplications.Count); // 3 fills where applied + Assert.IsType>(this.img.ProcessorApplications[0].processor); + } + + [Fact] + public void FillsForEachACharachterWhenBrushSetDefaultOptions() + { + this.img.DrawText("123", this.Font, Brushes.Solid(Rgba32.Red), path); + + Assert.NotEmpty(this.img.ProcessorApplications); + Assert.Equal(3, this.img.ProcessorApplications.Count); // 3 fills where applied + Assert.IsType>(this.img.ProcessorApplications[0].processor); + } + + [Fact] + public void FillsForEachACharachterWhenColorSet() + { + this.img.DrawText("123", this.Font, Rgba32.Red, path, new TextGraphicsOptions(true)); + + Assert.NotEmpty(this.img.ProcessorApplications); + Assert.Equal(3, this.img.ProcessorApplications.Count); + FillRegionProcessor processor = + Assert.IsType>(this.img.ProcessorApplications[0].processor); + + SolidBrush brush = Assert.IsType>(processor.Brush); + Assert.Equal(Rgba32.Red, brush.Color); + } + + [Fact] + public void FillsForEachACharachterWhenColorSetDefaultOptions() + { + this.img.DrawText("123", this.Font, Rgba32.Red, path); + + Assert.NotEmpty(this.img.ProcessorApplications); + Assert.Equal(3, this.img.ProcessorApplications.Count); + Assert.IsType>(this.img.ProcessorApplications[0].processor); + FillRegionProcessor processor = + Assert.IsType>(this.img.ProcessorApplications[0].processor); + + SolidBrush brush = Assert.IsType>(processor.Brush); + Assert.Equal(Rgba32.Red, brush.Color); + } + + [Fact] + public void DrawForEachACharachterWhenPenSetAndNotBrush() + { + this.img.DrawText( + "123", + this.Font, + null, + Pens.Dash(Rgba32.Red, 1), + path, + new TextGraphicsOptions(true)); + + Assert.NotEmpty(this.img.ProcessorApplications); + Assert.Equal(3, this.img.ProcessorApplications.Count); // 3 fills where applied + Assert.IsType>(this.img.ProcessorApplications[0].processor); + } + + [Fact] + public void DrawForEachACharachterWhenPenSetAndNotBrushDefaultOptions() + { + this.img.DrawText("123", this.Font, null, Pens.Dash(Rgba32.Red, 1), path); + + Assert.NotEmpty(this.img.ProcessorApplications); + Assert.Equal(3, this.img.ProcessorApplications.Count); // 3 fills where applied + Assert.IsType>(this.img.ProcessorApplications[0].processor); + } + + [Fact] + public void DrawForEachACharachterWhenPenSet() + { + this.img.DrawText("123", this.Font, Pens.Dash(Rgba32.Red, 1), path, new TextGraphicsOptions(true)); + + Assert.NotEmpty(this.img.ProcessorApplications); + Assert.Equal(3, this.img.ProcessorApplications.Count); // 3 fills where applied + Assert.IsType>(this.img.ProcessorApplications[0].processor); + } + + [Fact] + public void DrawForEachACharachterWhenPenSetDefaultOptions() + { + this.img.DrawText("123", this.Font, Pens.Dash(Rgba32.Red, 1), path); + + Assert.NotEmpty(this.img.ProcessorApplications); + Assert.Equal(3, this.img.ProcessorApplications.Count); // 3 fills where applied + Assert.IsType>(this.img.ProcessorApplications[0].processor); + } + + [Fact] + public void DrawForEachACharachterWhenPenSetAndFillFroEachWhenBrushSet() + { + this.img.DrawText( + "123", + this.Font, + Brushes.Solid(Rgba32.Red), + Pens.Dash(Rgba32.Red, 1), + path, + new TextGraphicsOptions(true)); + + Assert.NotEmpty(this.img.ProcessorApplications); + Assert.Equal(6, this.img.ProcessorApplications.Count); + } + + [Fact] + public void DrawForEachACharachterWhenPenSetAndFillFroEachWhenBrushSetDefaultOptions() + { + this.img.DrawText("123", this.Font, Brushes.Solid(Rgba32.Red), Pens.Dash(Rgba32.Red, 1), path); + + Assert.NotEmpty(this.img.ProcessorApplications); + Assert.Equal(6, this.img.ProcessorApplications.Count); + } + + [Fact] + public void BrushAppliesBeforPen() + { + this.img.DrawText( + "1", + this.Font, + Brushes.Solid(Rgba32.Red), + Pens.Dash(Rgba32.Red, 1), + path, + new TextGraphicsOptions(true)); + + Assert.NotEmpty(this.img.ProcessorApplications); + Assert.Equal(2, this.img.ProcessorApplications.Count); + Assert.IsType>(this.img.ProcessorApplications[0].processor); + Assert.IsType>(this.img.ProcessorApplications[1].processor); + } + + [Fact] + public void BrushAppliesBeforPenDefaultOptions() + { + this.img.DrawText("1", this.Font, Brushes.Solid(Rgba32.Red), Pens.Dash(Rgba32.Red, 1), path); + + Assert.NotEmpty(this.img.ProcessorApplications); + Assert.Equal(2, this.img.ProcessorApplications.Count); + Assert.IsType>(this.img.ProcessorApplications[0].processor); + Assert.IsType>(this.img.ProcessorApplications[1].processor); + } + + [Fact] + public void GlyphHeightChangesBasedOnuseImageResolutionFlag() + { + this.img.MetaData.VerticalResolution = 1; + this.img.MetaData.HorizontalResolution = 1; + this.img.DrawText("1", this.Font, Brushes.Solid(Rgba32.Red), path, new TextGraphicsOptions(true) { + UseImageResolution = false + }); + + this.img.DrawText("1", this.Font, Brushes.Solid(Rgba32.Red), path, new TextGraphicsOptions(true) + { + UseImageResolution = true + }); + + Assert.NotEmpty(this.img.ProcessorApplications); + Assert.Equal(2, this.img.ProcessorApplications.Count); + FillRegionProcessor ownResolution = Assert.IsType>(this.img.ProcessorApplications[0].processor); + FillRegionProcessor imgResolution = Assert.IsType>(this.img.ProcessorApplications[1].processor); + + ShapeRegion ownRegion = Assert.IsType(ownResolution.Region); + ShapeRegion imgRegion = Assert.IsType(imgResolution.Region); + + // magic numbers based on the font used at well known resolutions + Assert.Equal(7.44, ownRegion.Shape.Bounds.Height, 2); + Assert.Equal(0.1, imgRegion.Shape.Bounds.Height, 2); + } + } +} From 3b9e332da36bbdff06f7996b509ef598d2688882 Mon Sep 17 00:00:00 2001 From: Scott Williams Date: Fri, 2 Jun 2017 18:51:49 +0100 Subject: [PATCH 4/4] update to latest Shapes release --- src/ImageSharp.Drawing/ImageSharp.Drawing.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj index 9d24c1777..13500b65a 100644 --- a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj +++ b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj @@ -36,7 +36,7 @@ - + All