Skip to content

Commit 08061ea

Browse files
Merge pull request #178 from SixLabors/js/text-path
Fix accuracy of drawing text along a path
2 parents 1b15fe9 + 287987a commit 08061ea

29 files changed

Lines changed: 354 additions & 200 deletions

File tree

samples/DrawShapesWithImageSharp/Program.cs

Lines changed: 54 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,11 @@ private static void OutputStars()
5252
DrawFatL();
5353

5454
DrawText("Hello World");
55+
5556
DrawText(
5657
"Hello World Hello World Hello World Hello World Hello World Hello World Hello World",
57-
new Path(new CubicBezierLineSegment(
58-
new Vector2(0, 0),
59-
new Vector2(150, -150),
60-
new Vector2(250, -150),
61-
new Vector2(400, 0))));
58+
new EllipsePolygon(PointF.Empty, 100));
59+
// new RectangularPolygon(PointF.Empty, new SizeF(100, 100)));
6260
}
6361

6462
private static void DrawText(string text)
@@ -73,17 +71,21 @@ private static void DrawText(string text)
7371

7472
private static void DrawText(string text, IPath path)
7573
{
76-
FontFamily fam = SystemFonts.Get("Arial");
77-
var font = new Font(fam, 30);
74+
FontFamily family = SystemFonts.Get("Arial");
75+
Font font = new(family, 30);
7876
TextOptions textOptions = new(font)
7977
{
8078
WrappingLength = path.ComputeLength(),
8179
VerticalAlignment = VerticalAlignment.Top,
82-
HorizontalAlignment = HorizontalAlignment.Center,
80+
HorizontalAlignment = HorizontalAlignment.Left,
81+
82+
// Enable this to test vertical layout mode.
83+
//LayoutMode = LayoutMode.VerticalLeftRight
8384
};
85+
8486
IPathCollection glyphs = TextBuilder.GenerateGlyphs(text, path, textOptions);
8587

86-
glyphs.SaveImage("Text-Path", text + ".png");
88+
glyphs.SaveImageWithPath(path, "Text-Path", text + ".png");
8789
}
8890

8991
private static void DrawFatL()
@@ -223,61 +225,67 @@ private static void OutputClippedRectangle()
223225

224226
public static void SaveImage(this IPath shape, params string[] path) => new PathCollection(shape).SaveImage(path);
225227

226-
public static void SaveImage(this IPathCollection shape, params string[] path)
228+
public static void SaveImage(this IPathCollection collection, params string[] path)
227229
{
228-
shape = shape.Translate(-shape.Bounds.Location) // touch top left
229-
.Translate(new Vector2(10)); // move in from top left
230+
// Offset the path collection to ensure our resultant image is
231+
// large enough to contain the rendered output.
232+
collection = collection.Translate(-collection.Bounds.Location);
230233

234+
int width = (int)(collection.Bounds.Left + collection.Bounds.Right);
235+
int height = (int)(collection.Bounds.Top + collection.Bounds.Bottom);
236+
using var img = new Image<Rgba32>(width, height);
237+
238+
// Fill the canvas background and draw our shape
239+
img.Mutate(i => i.Fill(Color.DarkBlue));
240+
241+
// Draw our path collection.
242+
img.Mutate(i => i.Fill(Color.HotPink, collection));
243+
244+
// Ensure directory exists
231245
string fullPath = IOPath.GetFullPath(IOPath.Combine("Output", IOPath.Combine(path)));
246+
IODirectory.CreateDirectory(IOPath.GetDirectoryName(fullPath));
247+
img.Save(fullPath);
248+
}
232249

233-
// pad even amount around shape
234-
int width = (int)(shape.Bounds.Left + shape.Bounds.Right);
235-
int height = (int)(shape.Bounds.Top + shape.Bounds.Bottom);
250+
public static void SaveImageWithPath(this IPathCollection collection, IPath shape, params string[] path)
251+
{
252+
// Offset the shape and path collection to ensure our resultant image is
253+
// large enough to contain the rendered output.
254+
shape = shape.Translate(-collection.Bounds.Location);
255+
collection = collection.Translate(-collection.Bounds.Location);
236256

237-
using (var img = new Image<Rgba32>(width, height))
238-
{
239-
img.Mutate(i => i.Fill(Color.DarkBlue));
257+
var bounds = RectangleF.Union(shape.Bounds, collection.Bounds);
258+
int width = (int)(bounds.Left + bounds.Right);
259+
int height = (int)(bounds.Top + bounds.Bottom);
240260

241-
foreach (IPath s in shape)
242-
{
243-
// In ImageSharp.Drawing.Paths there is an extension method that takes in an IShape directly.
244-
img.Mutate(i => i.Fill(Color.HotPink, s));
245-
}
261+
using var img = new Image<Rgba32>(width, height);
246262

247-
// img.Draw(Color.LawnGreen, 1, new ShapePath(shape));
263+
// Fill the canvas background and draw our shape
264+
img.Mutate(i => i.Fill(Color.DarkBlue).Fill(Color.White.WithAlpha(.25F), shape));
248265

249-
// Ensure directory exists
250-
IODirectory.CreateDirectory(IOPath.GetDirectoryName(fullPath));
266+
// Draw our path collection.
267+
img.Mutate(i => i.Fill(Color.HotPink, collection));
251268

252-
img.Save(fullPath);
253-
}
269+
// Ensure directory exists
270+
string fullPath = IOPath.GetFullPath(IOPath.Combine("Output", IOPath.Combine(path)));
271+
IODirectory.CreateDirectory(IOPath.GetDirectoryName(fullPath));
272+
img.Save(fullPath);
254273
}
255274

256275
public static void SaveImage(this IPath shape, int width, int height, params string[] path)
257276
=> new PathCollection(shape).SaveImage(width, height, path);
258277

259278
public static void SaveImage(this IPathCollection shape, int width, int height, params string[] path)
260279
{
261-
string fullPath = IOPath.GetFullPath(IOPath.Combine("Output", IOPath.Combine(path)));
262-
263-
using (var img = new Image<Rgba32>(width, height))
264-
{
265-
img.Mutate(i => i.Fill(Color.DarkBlue));
266-
267-
// In ImageSharp.Drawing.Paths there is an extension method that takes in an IShape directly.
268-
foreach (IPath s in shape)
269-
{
270-
// In ImageSharp.Drawing.Paths there is an extension method that takes in an IShape directly.
271-
img.Mutate(i => i.Fill(Color.HotPink, s));
272-
}
280+
using var img = new Image<Rgba32>(width, height);
281+
img.Mutate(i => i.Fill(Color.DarkBlue));
282+
img.Mutate(i => i.Fill(Color.HotPink, shape));
273283

274-
// img.Draw(Color.LawnGreen, 1, new ShapePath(shape));
275-
276-
// Ensure directory exists
277-
IODirectory.CreateDirectory(IOPath.GetDirectoryName(fullPath));
284+
// Ensure directory exists
285+
string fullPath = IOPath.GetFullPath(IOPath.Combine("Output", IOPath.Combine(path)));
286+
IODirectory.CreateDirectory(IOPath.GetDirectoryName(fullPath));
278287

279-
img.Save(fullPath);
280-
}
288+
img.Save(fullPath);
281289
}
282290
}
283291
}

src/ImageSharp.Drawing/ImageSharp.Drawing.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
<None Include="..\..\shared-infrastructure\branding\icons\imagesharp.drawing\sixlabors.imagesharp.drawing.128.png" Pack="true" PackagePath="" />
1818
</ItemGroup>
1919
<ItemGroup>
20-
<PackageReference Include="SixLabors.Fonts" Version="1.0.0-beta16" />
21-
<PackageReference Include="SixLabors.ImageSharp" Version="2.1.1-alpha.0.1" />
20+
<PackageReference Include="SixLabors.Fonts" Version="1.0.0-beta16.13" />
21+
<PackageReference Include="SixLabors.ImageSharp" Version="2.1.1-alpha.0.2" />
2222
</ItemGroup>
2323
<Import Project="..\..\shared-infrastructure\src\SharedInfrastructure\SharedInfrastructure.projitems" Label="Shared" />
2424
</Project>

0 commit comments

Comments
 (0)