mirror of https://github.com/SixLabors/ImageSharp
committed by
GitHub
13 changed files with 926 additions and 0 deletions
@ -0,0 +1,203 @@ |
|||
// <copyright file="DrawText.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System.Numerics; |
|||
|
|||
using Drawing; |
|||
using Drawing.Brushes; |
|||
using Drawing.Pens; |
|||
|
|||
using SixLabors.Fonts; |
|||
|
|||
/// <summary>
|
|||
/// Extension methods for the <see cref="Image{TColor}"/> type.
|
|||
/// </summary>
|
|||
public static partial class ImageExtensions |
|||
{ |
|||
/// <summary>
|
|||
/// Draws the text onto the the image filled via the brush.
|
|||
/// </summary>
|
|||
/// <typeparam name="TColor">The type of the color.</typeparam>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="text">The text.</param>
|
|||
/// <param name="font">The font.</param>
|
|||
/// <param name="color">The color.</param>
|
|||
/// <param name="location">The location.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Image{TColor}" />.
|
|||
/// </returns>
|
|||
public static Image<TColor> DrawText<TColor>(this Image<TColor> source, string text, Font font, TColor color, Vector2 location) |
|||
where TColor : struct, IPixel<TColor> |
|||
{ |
|||
return source.DrawText(text, font, color, location, TextGraphicsOptions.Default); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws the text onto the the image filled via the brush.
|
|||
/// </summary>
|
|||
/// <typeparam name="TColor">The type of the color.</typeparam>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="text">The text.</param>
|
|||
/// <param name="font">The font.</param>
|
|||
/// <param name="color">The color.</param>
|
|||
/// <param name="location">The location.</param>
|
|||
/// <param name="options">The options.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Image{TColor}" />.
|
|||
/// </returns>
|
|||
public static Image<TColor> DrawText<TColor>(this Image<TColor> source, string text, Font font, TColor color, Vector2 location, TextGraphicsOptions options) |
|||
where TColor : struct, IPixel<TColor> |
|||
{ |
|||
return source.DrawText(text, font, Brushes<TColor>.Solid(color), null, location, options); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws the text onto the the image filled via the brush.
|
|||
/// </summary>
|
|||
/// <typeparam name="TColor">The type of the color.</typeparam>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="text">The text.</param>
|
|||
/// <param name="font">The font.</param>
|
|||
/// <param name="brush">The brush.</param>
|
|||
/// <param name="location">The location.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Image{TColor}" />.
|
|||
/// </returns>
|
|||
public static Image<TColor> DrawText<TColor>(this Image<TColor> source, string text, Font font, IBrush<TColor> brush, Vector2 location) |
|||
where TColor : struct, IPixel<TColor> |
|||
{ |
|||
return source.DrawText(text, font, brush, location, TextGraphicsOptions.Default); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws the text onto the the image filled via the brush.
|
|||
/// </summary>
|
|||
/// <typeparam name="TColor">The type of the color.</typeparam>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="text">The text.</param>
|
|||
/// <param name="font">The font.</param>
|
|||
/// <param name="brush">The brush.</param>
|
|||
/// <param name="location">The location.</param>
|
|||
/// <param name="options">The options.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Image{TColor}" />.
|
|||
/// </returns>
|
|||
public static Image<TColor> DrawText<TColor>(this Image<TColor> source, string text, Font font, IBrush<TColor> brush, Vector2 location, TextGraphicsOptions options) |
|||
where TColor : struct, IPixel<TColor> |
|||
{ |
|||
return source.DrawText(text, font, brush, null, location, options); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws the text onto the the image outlined via the pen.
|
|||
/// </summary>
|
|||
/// <typeparam name="TColor">The type of the color.</typeparam>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="text">The text.</param>
|
|||
/// <param name="font">The font.</param>
|
|||
/// <param name="pen">The pen.</param>
|
|||
/// <param name="location">The location.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Image{TColor}" />.
|
|||
/// </returns>
|
|||
public static Image<TColor> DrawText<TColor>(this Image<TColor> source, string text, Font font, IPen<TColor> pen, Vector2 location) |
|||
where TColor : struct, IPixel<TColor> |
|||
{ |
|||
return source.DrawText(text, font, pen, location, TextGraphicsOptions.Default); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws the text onto the the image outlined via the pen.
|
|||
/// </summary>
|
|||
/// <typeparam name="TColor">The type of the color.</typeparam>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="text">The text.</param>
|
|||
/// <param name="font">The font.</param>
|
|||
/// <param name="pen">The pen.</param>
|
|||
/// <param name="location">The location.</param>
|
|||
/// <param name="options">The options.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Image{TColor}" />.
|
|||
/// </returns>
|
|||
public static Image<TColor> DrawText<TColor>(this Image<TColor> source, string text, Font font, IPen<TColor> pen, Vector2 location, TextGraphicsOptions options) |
|||
where TColor : struct, IPixel<TColor> |
|||
{ |
|||
return source.DrawText(text, font, null, pen, location, options); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws the text onto the the image filled via the brush then outlined via the pen.
|
|||
/// </summary>
|
|||
/// <typeparam name="TColor">The type of the color.</typeparam>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="text">The text.</param>
|
|||
/// <param name="font">The font.</param>
|
|||
/// <param name="brush">The brush.</param>
|
|||
/// <param name="pen">The pen.</param>
|
|||
/// <param name="location">The location.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Image{TColor}" />.
|
|||
/// </returns>
|
|||
public static Image<TColor> DrawText<TColor>(this Image<TColor> source, string text, Font font, IBrush<TColor> brush, IPen<TColor> pen, Vector2 location) |
|||
where TColor : struct, IPixel<TColor> |
|||
{ |
|||
return source.DrawText(text, font, brush, pen, location, TextGraphicsOptions.Default); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws the text onto the the image filled via the brush then outlined via the pen.
|
|||
/// </summary>
|
|||
/// <typeparam name="TColor">The type of the color.</typeparam>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="text">The text.</param>
|
|||
/// <param name="font">The font.</param>
|
|||
/// <param name="brush">The brush.</param>
|
|||
/// <param name="pen">The pen.</param>
|
|||
/// <param name="location">The location.</param>
|
|||
/// <param name="options">The options.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Image{TColor}" />.
|
|||
/// </returns>
|
|||
public static Image<TColor> DrawText<TColor>(this Image<TColor> source, string text, Font font, IBrush<TColor> brush, IPen<TColor> pen, Vector2 location, TextGraphicsOptions options) |
|||
where TColor : struct, IPixel<TColor> |
|||
{ |
|||
GlyphBuilder glyphBuilder = new GlyphBuilder(location); |
|||
|
|||
TextRenderer renderer = new TextRenderer(glyphBuilder); |
|||
|
|||
Vector2 dpi = new Vector2((float)source.MetaData.HorizontalResolution, (float)source.MetaData.VerticalResolution); |
|||
FontSpan style = new FontSpan(font) |
|||
{ |
|||
ApplyKerning = options.ApplyKerning, |
|||
TabWidth = options.TabWidth |
|||
}; |
|||
|
|||
renderer.RenderText(text, style, dpi); |
|||
|
|||
System.Collections.Generic.IEnumerable<SixLabors.Shapes.IPath> shapesToDraw = glyphBuilder.Paths; |
|||
|
|||
GraphicsOptions pathOptions = (GraphicsOptions)options; |
|||
if (brush != null) |
|||
{ |
|||
foreach (SixLabors.Shapes.IPath s in shapesToDraw) |
|||
{ |
|||
source.Fill(brush, s, pathOptions); |
|||
} |
|||
} |
|||
|
|||
if (pen != null) |
|||
{ |
|||
foreach (SixLabors.Shapes.IPath s in shapesToDraw) |
|||
{ |
|||
source.Draw(pen, s, pathOptions); |
|||
} |
|||
} |
|||
|
|||
return source; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,126 @@ |
|||
// <copyright file="GlyphBuilder.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.Drawing |
|||
{ |
|||
using System.Collections.Generic; |
|||
using System.Numerics; |
|||
|
|||
using SixLabors.Fonts; |
|||
using SixLabors.Shapes; |
|||
|
|||
/// <summary>
|
|||
/// rendering surface that Fonts can use to generate Shapes.
|
|||
/// </summary>
|
|||
internal class GlyphBuilder : IGlyphRenderer |
|||
{ |
|||
private readonly PathBuilder builder = new PathBuilder(); |
|||
private readonly List<IPath> paths = new List<IPath>(); |
|||
private Vector2 currentPoint = default(Vector2); |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="GlyphBuilder"/> class.
|
|||
/// </summary>
|
|||
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(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="GlyphBuilder"/> class.
|
|||
/// </summary>
|
|||
/// <param name="origin">The origin.</param>
|
|||
public GlyphBuilder(Vector2 origin) |
|||
{ |
|||
this.builder = new PathBuilder(); |
|||
this.builder.SetOrigin(origin); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the paths that have been rendered by this.
|
|||
/// </summary>
|
|||
public IEnumerable<IPath> Paths => this.paths; |
|||
|
|||
/// <summary>
|
|||
/// Begins the glyph.
|
|||
/// </summary>
|
|||
void IGlyphRenderer.BeginGlyph() |
|||
{ |
|||
this.builder.Clear(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Begins the figure.
|
|||
/// </summary>
|
|||
void IGlyphRenderer.BeginFigure() |
|||
{ |
|||
this.builder.StartFigure(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws a cubic bezier from the current point to the <paramref name="point"/>
|
|||
/// </summary>
|
|||
/// <param name="secondControlPoint">The second control point.</param>
|
|||
/// <param name="thirdControlPoint">The third control point.</param>
|
|||
/// <param name="point">The point.</param>
|
|||
void IGlyphRenderer.CubicBezierTo(Vector2 secondControlPoint, Vector2 thirdControlPoint, Vector2 point) |
|||
{ |
|||
this.builder.AddBezier(this.currentPoint, secondControlPoint, thirdControlPoint, point); |
|||
this.currentPoint = point; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Ends the glyph.
|
|||
/// </summary>
|
|||
void IGlyphRenderer.EndGlyph() |
|||
{ |
|||
this.paths.Add(this.builder.Build()); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Ends the figure.
|
|||
/// </summary>
|
|||
void IGlyphRenderer.EndFigure() |
|||
{ |
|||
this.builder.CloseFigure(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws a line from the current point to the <paramref name="point"/>.
|
|||
/// </summary>
|
|||
/// <param name="point">The point.</param>
|
|||
void IGlyphRenderer.LineTo(Vector2 point) |
|||
{ |
|||
this.builder.AddLine(this.currentPoint, point); |
|||
this.currentPoint = point; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Moves to current point to the supplied vector.
|
|||
/// </summary>
|
|||
/// <param name="point">The point.</param>
|
|||
void IGlyphRenderer.MoveTo(Vector2 point) |
|||
{ |
|||
this.builder.StartFigure(); |
|||
this.currentPoint = point; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws a quadratics bezier from the current point to the <paramref name="point"/>
|
|||
/// </summary>
|
|||
/// <param name="secondControlPoint">The second control point.</param>
|
|||
/// <param name="point">The point.</param>
|
|||
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; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,25 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|||
<PropertyGroup> |
|||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion> |
|||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> |
|||
</PropertyGroup> |
|||
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" /> |
|||
<PropertyGroup Label="Globals"> |
|||
<ProjectGuid>329d7698-65bc-48ad-a16f-428682964493</ProjectGuid> |
|||
<RootNamespace>ImageSharp.Drawing</RootNamespace> |
|||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath> |
|||
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath> |
|||
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion> |
|||
</PropertyGroup> |
|||
<PropertyGroup> |
|||
<SchemaVersion>2.0</SchemaVersion> |
|||
</PropertyGroup> |
|||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> |
|||
<ProduceOutputsOnBuild>True</ProduceOutputsOnBuild> |
|||
</PropertyGroup> |
|||
<ItemGroup> |
|||
<Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" /> |
|||
</ItemGroup> |
|||
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" /> |
|||
</Project> |
|||
@ -0,0 +1,6 @@ |
|||
// <copyright file="AssemblyInfo.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
// Common values read from `AssemblyInfo.Common.cs`
|
|||
@ -0,0 +1,68 @@ |
|||
// <copyright file="TextGraphicsOptions.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.Drawing |
|||
{ |
|||
/// <summary>
|
|||
/// Options for influencing the drawing functions.
|
|||
/// </summary>
|
|||
public struct TextGraphicsOptions |
|||
{ |
|||
/// <summary>
|
|||
/// Represents the default <see cref="TextGraphicsOptions"/>.
|
|||
/// </summary>
|
|||
public static readonly TextGraphicsOptions Default = new TextGraphicsOptions(true); |
|||
|
|||
/// <summary>
|
|||
/// Whether antialiasing should be applied.
|
|||
/// </summary>
|
|||
public bool Antialias; |
|||
|
|||
/// <summary>
|
|||
/// Whether the text should be drawing with kerning enabled.
|
|||
/// </summary>
|
|||
public bool ApplyKerning; |
|||
|
|||
/// <summary>
|
|||
/// The number of space widths a tab should lock to.
|
|||
/// </summary>
|
|||
public float TabWidth; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="TextGraphicsOptions" /> struct.
|
|||
/// </summary>
|
|||
/// <param name="enableAntialiasing">If set to <c>true</c> [enable antialiasing].</param>
|
|||
public TextGraphicsOptions(bool enableAntialiasing) |
|||
{ |
|||
this.Antialias = enableAntialiasing; |
|||
this.ApplyKerning = true; |
|||
this.TabWidth = 4; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs an implicit conversion from <see cref="GraphicsOptions"/> to <see cref="TextGraphicsOptions"/>.
|
|||
/// </summary>
|
|||
/// <param name="options">The options.</param>
|
|||
/// <returns>
|
|||
/// The result of the conversion.
|
|||
/// </returns>
|
|||
public static implicit operator TextGraphicsOptions(GraphicsOptions options) |
|||
{ |
|||
return new TextGraphicsOptions(options.Antialias); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs an explicit conversion from <see cref="TextGraphicsOptions"/> to <see cref="GraphicsOptions"/>.
|
|||
/// </summary>
|
|||
/// <param name="options">The options.</param>
|
|||
/// <returns>
|
|||
/// The result of the conversion.
|
|||
/// </returns>
|
|||
public static explicit operator GraphicsOptions(TextGraphicsOptions options) |
|||
{ |
|||
return new GraphicsOptions(options.Antialias); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,95 @@ |
|||
{ |
|||
"version": "1.0.0-alpha2-*", |
|||
"title": "ImageSharp.Drawing.Text", |
|||
"description": "A cross-platform library for the processing of image files; written in C#", |
|||
"authors": [ |
|||
"James Jackson-South and contributors" |
|||
], |
|||
"packOptions": { |
|||
"owners": [ |
|||
"James Jackson-South and contributors" |
|||
], |
|||
"projectUrl": "https://github.com/JimBobSquarePants/ImageSharp", |
|||
"licenseUrl": "http://www.apache.org/licenses/LICENSE-2.0", |
|||
"iconUrl": "https://raw.githubusercontent.com/JimBobSquarePants/ImageSharp/master/build/icons/imagesharp-logo-128.png", |
|||
"requireLicenseAcceptance": false, |
|||
"repository": { |
|||
"type": "git", |
|||
"url": "https://github.com/JimBobSquarePants/ImageSharp" |
|||
}, |
|||
"tags": [ |
|||
"Image Resize Crop Gif Jpg Jpeg Bitmap Png Core" |
|||
] |
|||
}, |
|||
"buildOptions": { |
|||
"allowUnsafe": true, |
|||
"xmlDoc": true, |
|||
"additionalArguments": [ "/additionalfile:../Shared/stylecop.json", "/ruleset:../../ImageSharp.ruleset" ], |
|||
"compile": [ |
|||
"../Shared/*.cs" |
|||
] |
|||
}, |
|||
"configurations": { |
|||
"Release": { |
|||
"buildOptions": { |
|||
"warningsAsErrors": true, |
|||
"optimize": true |
|||
} |
|||
} |
|||
}, |
|||
"dependencies": { |
|||
"ImageSharp": { |
|||
"target": "project" |
|||
}, |
|||
"SixLabors.Fonts": "0.1.0-alpha0001", |
|||
"ImageSharp.Drawing.Paths": { |
|||
"target": "project" |
|||
}, |
|||
"StyleCop.Analyzers": { |
|||
"version": "1.0.0", |
|||
"type": "build" |
|||
}, |
|||
"System.Buffers": "4.0.0", |
|||
"System.Runtime.CompilerServices.Unsafe": "4.0.0" |
|||
}, |
|||
"frameworks": { |
|||
"netstandard1.1": { |
|||
"dependencies": { |
|||
"System.Collections": "4.0.11", |
|||
"System.Diagnostics.Debug": "4.0.11", |
|||
"System.Diagnostics.Tools": "4.0.1", |
|||
"System.IO": "4.1.0", |
|||
"System.IO.Compression": "4.1.0", |
|||
"System.Linq": "4.1.0", |
|||
"System.Numerics.Vectors": "4.1.1", |
|||
"System.ObjectModel": "4.0.12", |
|||
"System.Resources.ResourceManager": "4.0.1", |
|||
"System.Runtime.Extensions": "4.1.0", |
|||
"System.Runtime.InteropServices": "4.1.0", |
|||
"System.Runtime.Numerics": "4.0.1", |
|||
"System.Text.Encoding.Extensions": "4.0.11", |
|||
"System.Threading": "4.0.11", |
|||
"System.Threading.Tasks": "4.0.11", |
|||
"System.Threading.Tasks.Parallel": "4.0.1" |
|||
} |
|||
}, |
|||
"net45": { |
|||
"dependencies": { |
|||
"System.Numerics.Vectors": "4.1.1", |
|||
"System.Threading.Tasks.Parallel": "4.0.0" |
|||
}, |
|||
"frameworkAssemblies": { |
|||
"System.Runtime": { "type": "build" } |
|||
} |
|||
}, |
|||
"net461": { |
|||
"dependencies": { |
|||
"System.Threading.Tasks.Parallel": "4.0.0" |
|||
}, |
|||
"frameworkAssemblies": { |
|||
"System.Runtime": { "type": "build" }, |
|||
"System.Numerics": "4.0.0.0" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,194 @@ |
|||
|
|||
namespace ImageSharp.Tests.Drawing.Text |
|||
{ |
|||
using System; |
|||
using System.IO; |
|||
using ImageSharp; |
|||
using ImageSharp.Drawing.Brushes; |
|||
using Processing; |
|||
using System.Collections.Generic; |
|||
using Xunit; |
|||
using ImageSharp.Drawing; |
|||
using System.Numerics; |
|||
using SixLabors.Shapes; |
|||
using ImageSharp.Drawing.Processors; |
|||
using ImageSharp.Drawing.Pens; |
|||
using SixLabors.Fonts; |
|||
using Paths; |
|||
|
|||
public class DrawText : IDisposable |
|||
{ |
|||
Color color = Color.HotPink; |
|||
SolidBrush brush = Brushes.Solid(Color.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() |
|||
{ |
|||
this.FontCollection = new FontCollection(); |
|||
this.Font = FontCollection.Install(TestFontUtilities.GetPath("SixLaborsSampleAB.woff")); |
|||
this.img = new ProcessorWatchingImage(10, 10); |
|||
} |
|||
|
|||
public void Dispose() |
|||
{ |
|||
img.Dispose(); |
|||
} |
|||
|
|||
[Fact] |
|||
public void FillsForEachACharachterWhenBrushSetAndNotPen() |
|||
{ |
|||
img.DrawText("123", this.Font, Brushes.Solid(Color.Red), null, Vector2.Zero, new TextGraphicsOptions(true)); |
|||
|
|||
Assert.NotEmpty(img.ProcessorApplications); |
|||
Assert.Equal(3, img.ProcessorApplications.Count); // 3 fills where applied
|
|||
Assert.IsType<FillRegionProcessor<Color>>(img.ProcessorApplications[0].processor); |
|||
} |
|||
|
|||
[Fact] |
|||
public void FillsForEachACharachterWhenBrushSetAndNotPenDefaultOptions() |
|||
{ |
|||
img.DrawText("123", this.Font, Brushes.Solid(Color.Red), null, Vector2.Zero); |
|||
|
|||
Assert.NotEmpty(img.ProcessorApplications); |
|||
Assert.Equal(3, img.ProcessorApplications.Count); // 3 fills where applied
|
|||
Assert.IsType<FillRegionProcessor<Color>>(img.ProcessorApplications[0].processor); |
|||
} |
|||
|
|||
|
|||
[Fact] |
|||
public void FillsForEachACharachterWhenBrushSet() |
|||
{ |
|||
img.DrawText("123", this.Font, Brushes.Solid(Color.Red), Vector2.Zero, new TextGraphicsOptions(true)); |
|||
|
|||
Assert.NotEmpty(img.ProcessorApplications); |
|||
Assert.Equal(3, img.ProcessorApplications.Count); // 3 fills where applied
|
|||
Assert.IsType<FillRegionProcessor<Color>>(img.ProcessorApplications[0].processor); |
|||
} |
|||
|
|||
[Fact] |
|||
public void FillsForEachACharachterWhenBrushSetDefaultOptions() |
|||
{ |
|||
img.DrawText("123", this.Font, Brushes.Solid(Color.Red), Vector2.Zero); |
|||
|
|||
Assert.NotEmpty(img.ProcessorApplications); |
|||
Assert.Equal(3, img.ProcessorApplications.Count); // 3 fills where applied
|
|||
Assert.IsType<FillRegionProcessor<Color>>(img.ProcessorApplications[0].processor); |
|||
} |
|||
|
|||
[Fact] |
|||
public void FillsForEachACharachterWhenColorSet() |
|||
{ |
|||
img.DrawText("123", this.Font, Color.Red, Vector2.Zero, new TextGraphicsOptions(true)); |
|||
|
|||
Assert.NotEmpty(img.ProcessorApplications); |
|||
Assert.Equal(3, img.ProcessorApplications.Count); |
|||
FillRegionProcessor<Color> processor = Assert.IsType<FillRegionProcessor<Color>>(img.ProcessorApplications[0].processor); |
|||
|
|||
SolidBrush<Color> brush = Assert.IsType<SolidBrush<Color>>(processor.Brush); |
|||
Assert.Equal(Color.Red, brush.Color); |
|||
} |
|||
|
|||
[Fact] |
|||
public void FillsForEachACharachterWhenColorSetDefaultOptions() |
|||
{ |
|||
img.DrawText("123", this.Font, Color.Red, Vector2.Zero); |
|||
|
|||
Assert.NotEmpty(img.ProcessorApplications); |
|||
Assert.Equal(3, img.ProcessorApplications.Count); |
|||
Assert.IsType<FillRegionProcessor<Color>>(img.ProcessorApplications[0].processor); |
|||
FillRegionProcessor<Color> processor = Assert.IsType<FillRegionProcessor<Color>>(img.ProcessorApplications[0].processor); |
|||
|
|||
SolidBrush<Color> brush = Assert.IsType<SolidBrush<Color>>(processor.Brush); |
|||
Assert.Equal(Color.Red, brush.Color); |
|||
} |
|||
|
|||
[Fact] |
|||
public void DrawForEachACharachterWhenPenSetAndNotBrush() |
|||
{ |
|||
img.DrawText("123", this.Font, null, Pens.Dash(Color.Red, 1), Vector2.Zero, new TextGraphicsOptions(true)); |
|||
|
|||
Assert.NotEmpty(img.ProcessorApplications); |
|||
Assert.Equal(3, img.ProcessorApplications.Count); // 3 fills where applied
|
|||
Assert.IsType<DrawPathProcessor<Color>>(img.ProcessorApplications[0].processor); |
|||
} |
|||
|
|||
[Fact] |
|||
public void DrawForEachACharachterWhenPenSetAndNotBrushDefaultOptions() |
|||
{ |
|||
img.DrawText("123", this.Font, null, Pens.Dash(Color.Red, 1), Vector2.Zero); |
|||
|
|||
Assert.NotEmpty(img.ProcessorApplications); |
|||
Assert.Equal(3, img.ProcessorApplications.Count); // 3 fills where applied
|
|||
Assert.IsType<DrawPathProcessor<Color>>(img.ProcessorApplications[0].processor); |
|||
} |
|||
|
|||
|
|||
[Fact] |
|||
public void DrawForEachACharachterWhenPenSet() |
|||
{ |
|||
img.DrawText("123", this.Font, Pens.Dash(Color.Red, 1), Vector2.Zero, new TextGraphicsOptions(true)); |
|||
|
|||
Assert.NotEmpty(img.ProcessorApplications); |
|||
Assert.Equal(3, img.ProcessorApplications.Count); // 3 fills where applied
|
|||
Assert.IsType<DrawPathProcessor<Color>>(img.ProcessorApplications[0].processor); |
|||
} |
|||
|
|||
[Fact] |
|||
public void DrawForEachACharachterWhenPenSetDefaultOptions() |
|||
{ |
|||
img.DrawText("123", this.Font, Pens.Dash(Color.Red, 1), Vector2.Zero); |
|||
|
|||
Assert.NotEmpty(img.ProcessorApplications); |
|||
Assert.Equal(3, img.ProcessorApplications.Count); // 3 fills where applied
|
|||
Assert.IsType<DrawPathProcessor<Color>>(img.ProcessorApplications[0].processor); |
|||
} |
|||
|
|||
[Fact] |
|||
public void DrawForEachACharachterWhenPenSetAndFillFroEachWhenBrushSet() |
|||
{ |
|||
img.DrawText("123", this.Font, Brushes.Solid(Color.Red), Pens.Dash(Color.Red, 1), Vector2.Zero, new TextGraphicsOptions(true)); |
|||
|
|||
Assert.NotEmpty(img.ProcessorApplications); |
|||
Assert.Equal(6, img.ProcessorApplications.Count); |
|||
} |
|||
|
|||
[Fact] |
|||
public void DrawForEachACharachterWhenPenSetAndFillFroEachWhenBrushSetDefaultOptions() |
|||
{ |
|||
img.DrawText("123", this.Font, Brushes.Solid(Color.Red), Pens.Dash(Color.Red, 1), Vector2.Zero); |
|||
|
|||
Assert.NotEmpty(img.ProcessorApplications); |
|||
Assert.Equal(6, img.ProcessorApplications.Count); |
|||
} |
|||
|
|||
[Fact] |
|||
public void BrushAppliesBeforPen() |
|||
{ |
|||
img.DrawText("1", this.Font, Brushes.Solid(Color.Red), Pens.Dash(Color.Red, 1), Vector2.Zero, new TextGraphicsOptions(true)); |
|||
|
|||
Assert.NotEmpty(img.ProcessorApplications); |
|||
Assert.Equal(2, img.ProcessorApplications.Count); |
|||
Assert.IsType<FillRegionProcessor<Color>>(img.ProcessorApplications[0].processor); |
|||
Assert.IsType<DrawPathProcessor<Color>>(img.ProcessorApplications[1].processor); |
|||
} |
|||
|
|||
[Fact] |
|||
public void BrushAppliesBeforPenDefaultOptions() |
|||
{ |
|||
img.DrawText("1", this.Font, Brushes.Solid(Color.Red), Pens.Dash(Color.Red, 1), Vector2.Zero); |
|||
|
|||
Assert.NotEmpty(img.ProcessorApplications); |
|||
Assert.Equal(2, img.ProcessorApplications.Count); |
|||
Assert.IsType<FillRegionProcessor<Color>>(img.ProcessorApplications[0].processor); |
|||
Assert.IsType<DrawPathProcessor<Color>>(img.ProcessorApplications[1].processor); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,68 @@ |
|||
|
|||
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
|
|||
var fullBuilder = new GlyphBuilder(new System.Numerics.Vector2(10, 99)); |
|||
IGlyphRenderer builder = fullBuilder; |
|||
|
|||
builder.BeginGlyph(); |
|||
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(); |
|||
|
|||
var 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 (var i = 0; i < 10; i++) |
|||
{ |
|||
builder.BeginGlyph(); |
|||
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()); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,41 @@ |
|||
|
|||
namespace ImageSharp.Tests.Drawing.Text |
|||
{ |
|||
using System; |
|||
using System.IO; |
|||
using ImageSharp; |
|||
using ImageSharp.Drawing.Brushes; |
|||
using Processing; |
|||
using System.Collections.Generic; |
|||
using Xunit; |
|||
using ImageSharp.Drawing; |
|||
using System.Numerics; |
|||
using SixLabors.Shapes; |
|||
using ImageSharp.Drawing.Processors; |
|||
using ImageSharp.Drawing.Pens; |
|||
using SixLabors.Fonts; |
|||
|
|||
public class OutputText : FileTestBase |
|||
{ |
|||
private readonly FontCollection FontCollection; |
|||
private readonly Font Font; |
|||
|
|||
public OutputText() |
|||
{ |
|||
this.FontCollection = new FontCollection(); |
|||
this.Font = FontCollection.Install(TestFontUtilities.GetPath("SixLaborsSampleAB.woff")); |
|||
} |
|||
|
|||
[Fact] |
|||
public void DrawAB() |
|||
{ |
|||
//draws 2 overlapping triangle glyphs twice 1 set on each line
|
|||
using (var img = new Image(100, 200)) |
|||
{ |
|||
img.Fill(Color.DarkBlue) |
|||
.DrawText("AB\nAB", new Font(this.Font, 50), Color.Red, new Vector2(0, 0)); |
|||
img.Save($"{this.CreateOutputDirectory("Drawing", "Text")}/AB.png"); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,90 @@ |
|||
// <copyright file="TestImage.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.Tests |
|||
{ |
|||
using System; |
|||
using System.Collections.Concurrent; |
|||
using System.Collections.Generic; |
|||
using System.IO; |
|||
using System.Linq; |
|||
using System.Reflection; |
|||
|
|||
/// <summary>
|
|||
/// A test image file.
|
|||
/// </summary>
|
|||
public static class TestFontUtilities |
|||
{ |
|||
/// <summary>
|
|||
/// The formats directory.
|
|||
/// </summary>
|
|||
private static readonly string FormatsDirectory = GetFontsDirectory(); |
|||
|
|||
/// <summary>
|
|||
/// Gets the full qualified path to the file.
|
|||
/// </summary>
|
|||
/// <param name="file">
|
|||
/// The file path.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// The <see cref="string"/>.
|
|||
/// </returns>
|
|||
public static string GetPath(string file) |
|||
{ |
|||
return Path.Combine(FormatsDirectory, file); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the correct path to the formats directory.
|
|||
/// </summary>
|
|||
/// <returns>
|
|||
/// The <see cref="string"/>.
|
|||
/// </returns>
|
|||
private static string GetFontsDirectory() |
|||
{ |
|||
List<string> directories = new List< string > { |
|||
"TestFonts/", // Here for code coverage tests.
|
|||
"tests/ImageSharp.Tests/TestFonts/", // from travis/build script
|
|||
"../../../ImageSharp.Tests/TestFonts/", // from Sandbox46
|
|||
"../../../../TestFonts/" |
|||
}; |
|||
|
|||
directories = directories.SelectMany(x => new[] |
|||
{ |
|||
Path.GetFullPath(x) |
|||
}).ToList(); |
|||
|
|||
AddFormatsDirectoryFromTestAssebmlyPath(directories); |
|||
|
|||
var directory = directories.FirstOrDefault(x => Directory.Exists(x)); |
|||
|
|||
if(directory != null) |
|||
{ |
|||
return directory; |
|||
} |
|||
|
|||
throw new System.Exception($"Unable to find Fonts directory at any of these locations [{string.Join(", ", directories)}]"); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// The path returned by Path.GetFullPath(x) can be relative to dotnet framework directory
|
|||
/// in certain scenarios like dotTrace test profiling.
|
|||
/// This method calculates and adds the format directory based on the ImageSharp.Tests assembly location.
|
|||
/// </summary>
|
|||
/// <param name="directories">The directories list</param>
|
|||
private static void AddFormatsDirectoryFromTestAssebmlyPath(List<string> directories) |
|||
{ |
|||
string assemblyLocation = typeof(TestFile).GetTypeInfo().Assembly.Location; |
|||
assemblyLocation = Path.GetDirectoryName(assemblyLocation); |
|||
|
|||
if (assemblyLocation != null) |
|||
{ |
|||
string dirFromAssemblyLocation = Path.Combine(assemblyLocation, "../../../TestFonts/"); |
|||
dirFromAssemblyLocation = Path.GetFullPath(dirFromAssemblyLocation); |
|||
directories.Add(dirFromAssemblyLocation); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
Binary file not shown.
Loading…
Reference in new issue