Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ image.Mutate(ctx => ctx.Paint(canvas =>
{
canvas.Fill(Brushes.Solid(Color.White));
canvas.Fill(Brushes.Solid(Color.Red), new EllipsePolygon(200, 200, 100));
canvas.Draw(Pens.Solid(Color.Blue, 3F), new RectangularPolygon(50, 50, 200, 100));
canvas.Draw(Pens.Solid(Color.Blue, 3F), new RectanglePolygon(50, 50, 200, 100));
}));
```

Expand Down
24 changes: 12 additions & 12 deletions samples/DrawShapesWithImageSharp/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ private static void DrawPosterComposition()

// The lake is a plain rectangle filled with a vertical LinearGradientBrush. Building it
// with PathBuilder keeps the construction style identical to the surrounding shapes
// even though a RectangularPolygon would also work for an axis-aligned rectangle.
// even though a RectanglePolygon would also work for an axis-aligned rectangle.
PathBuilder lakeShape = new();
lakeShape.AddLines(
new PointF(0, 432),
Expand Down Expand Up @@ -175,7 +175,7 @@ private static void DrawPosterComposition()
// Save pushes a clipping state; Restore pops it. Anything drawn between the two is
// confined to lakeHighlight even though the brush spans its full bounding rectangle.
canvas.Save(lakeHighlightClipOptions, lakeHighlight);
canvas.Fill(Brushes.ForwardDiagonal(Color.White.WithAlpha(.36F), Color.Transparent), new RectangularPolygon(lakeHighlightBounds));
canvas.Fill(Brushes.ForwardDiagonal(Color.White.WithAlpha(.36F), Color.Transparent), new RectanglePolygon(lakeHighlightBounds));
canvas.Restore();

// Title panel: pushing posterPanelOptions onto the canvas with Save activates a
Expand Down Expand Up @@ -249,7 +249,7 @@ private static void DrawPosterComposition()

canvas.Save(posterPanelOptions);
canvas.SaveLayer(new GraphicsOptions { BlendPercentage = .94F }, posterPanelLayerBounds);
canvas.Fill(Brushes.Solid(Color.White.WithAlpha(.86F)), new RectangularPolygon(posterPanelBounds));
canvas.Fill(Brushes.Solid(Color.White.WithAlpha(.86F)), new RectanglePolygon(posterPanelBounds));
canvas.DrawText(posterTextOptions, posterText, Brushes.Solid(Color.DarkSlateGray), pen: null);
canvas.Restore();
canvas.Restore();
Expand Down Expand Up @@ -296,8 +296,8 @@ private static void DrawTransitMap()
pen: null);

// Legend panel: reuse the route pens so the key is drawn with the same stroke options as the map.
canvas.Fill(Brushes.Solid(Color.White.WithAlpha(.9F)), new RectangularPolygon(680, 46, 220, 126));
canvas.Draw(Pens.Solid(Color.LightSlateGray, 2), new RectangularPolygon(680, 46, 220, 126));
canvas.Fill(Brushes.Solid(Color.White.WithAlpha(.9F)), new RectanglePolygon(680, 46, 220, 126));
canvas.Draw(Pens.Solid(Color.LightSlateGray, 2), new RectanglePolygon(680, 46, 220, 126));
canvas.DrawLine(harborLinePen, new PointF(708, 78), new PointF(768, 78));
canvas.DrawLine(gardenLoopPen, new PointF(708, 112), new PointF(768, 112));
canvas.DrawLine(airportLinePen, new PointF(708, 146), new PointF(768, 146));
Expand Down Expand Up @@ -627,7 +627,7 @@ private static void DrawTypographySheet()
// options the draw call uses, otherwise WrappingLength, LineSpacing, or font fallback
// can change where the lines break and the box drifts off the text.
FontRectangle measuredBox = TextMeasurer.MeasureRenderableBounds(measuredText, measuredOptions);
RectangularPolygon measuredBackground = new(
RectanglePolygon measuredBackground = new(
measuredBox.X - 10,
measuredBox.Y - 8,
measuredBox.Width + 20,
Expand Down Expand Up @@ -852,9 +852,9 @@ static void DrawPanel(
Brush titleBrush,
Pen rulePen)
{
RectangularPolygon panel = new(origin.X, origin.Y, width, height);
RectanglePolygon panel = new(origin.X, origin.Y, width, height);

// RectangularPolygon implements IPath. The same shape can be both filled (with a
// RectanglePolygon implements IPath. The same shape can be both filled (with a
// semi-transparent brush) and stroked (with a pen), which keeps the panel framing
// consistent across the sheet without re-allocating geometry.
canvas.Fill(Brushes.Solid(Color.White.WithAlpha(.54F)), panel);
Expand Down Expand Up @@ -947,7 +947,7 @@ static void DrawBeforeAfterWipePanel(
// involved. A simple right-half rectangle is the entire mask, so OilPaint runs only
// on those pixels and the left half stays as the original photograph.
float midX = imageArea.X + (imageArea.Width / 2F);
RectangularPolygon afterRegion = new(
RectanglePolygon afterRegion = new(
midX,
imageArea.Y,
imageArea.Width / 2F,
Expand Down Expand Up @@ -1019,7 +1019,7 @@ static void DrawImageBrushPanel(
imageArea.Y + (imageArea.Height / 2F));
float outerRadius = (MathF.Min(imageArea.Width, imageArea.Height) / 2F) - 6F;
float innerRadius = outerRadius * 0.5F;
Star star = new(starCenter.X, starCenter.Y, 5, innerRadius, outerRadius);
StarPolygon star = new(starCenter.X, starCenter.Y, 5, innerRadius, outerRadius);

// ImageBrush samples the source image in world coordinates: a destination pixel at
// (x, y) reads source pixel (x - offset.X, y - offset.Y) inside SourceRegion. The
Expand Down Expand Up @@ -1080,7 +1080,7 @@ static void DrawPhotoInTextPanel(
ShapeOptions = new ShapeOptions { BooleanOperation = BooleanOperation.Intersection },
};

canvas.Fill(Brushes.Solid(Color.ParseHex("#E2DCC2")), new RectangularPolygon(imageArea));
canvas.Fill(Brushes.Solid(Color.ParseHex("#E2DCC2")), new RectanglePolygon(imageArea));
canvas.Save(clipToGlyphs, glyphClips);
canvas.DrawImage(source, source.Bounds, imageArea, null);
canvas.Restore();
Expand Down Expand Up @@ -1109,7 +1109,7 @@ static float DrawPanelChrome(
Color titleColor,
Color captionColor)
{
RectangularPolygon panelShape = new(panel);
RectanglePolygon panelShape = new(panel);
canvas.Fill(Brushes.Solid(Color.White), panelShape);
canvas.Draw(Pens.Solid(Color.ParseHex("#D7D2C0"), 1), panelShape);

Expand Down
2 changes: 1 addition & 1 deletion samples/DrawShapesWithImageSharp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ Image-compositing scene demonstrating four ways a photograph (`tests/Images/Inpu

- **Before / after wipe** — `canvas.Apply(rightHalfRect, ctx => ctx.OilPaint(15, 5))` scopes an `OilPaint` processor to the right half of the photograph.
- **Privacy redaction** — `canvas.Apply(ellipse, ctx => ctx.Pixelate(10))` pixelates an elliptical face-shaped region and leaves the rest untouched.
- **Image as a brush** — `new ImageBrush<Rgba32>(source, source.Bounds, brushOffset)` wraps the photograph as a `Brush` so a `Star` path can be filled with it as a texture; the brush offset aligns the mountain in the photograph with the star's centre.
- **Image as a brush** — `new ImageBrush<Rgba32>(source, source.Bounds, brushOffset)` wraps the photograph as a `Brush` so a `StarPolygon` path can be filled with it as a texture; the brush offset aligns the mountain in the photograph with the star's centre.
- **Photo in text** — `TextBuilder.GeneratePaths("MASK", ...)` produces one `IPath` per glyph; `canvas.Save(intersectionOptions, glyphPaths)` uses them as a compound clip so `DrawImage` only renders inside the letterforms.

## Running
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public override void Paint(DrawingCanvas canvas, TimeSpan deltaTime)
canvas.Apply(edgeRegion, ctx => ctx.DetectEdges());
canvas.Apply(blurRegion, ctx => ctx.GaussianBlur(Math.Max(3F, Math.Min(viewportSize.Width, viewportSize.Height) / 120F)));

canvas.Draw(Pens.Solid(OutlineColor, 3), new RectangularPolygon(edgeRegion));
canvas.Draw(Pens.Solid(OutlineColor, 3), new RectanglePolygon(edgeRegion));
canvas.Draw(Pens.Solid(OutlineColor, 3), blurRegion);
}

Expand Down
14 changes: 7 additions & 7 deletions samples/WebGPUExternalSurfaceDemo/Scenes/ManualTextFlowScene.cs
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,8 @@ public override void Paint(DrawingCanvas canvas, TimeSpan deltaTime)
this.cachedObstacleShape = this.obstacleShape;
}

canvas.Fill(PageBrush, new RectangularPolygon(pageLeft, pageTop, pageRight - pageLeft, pageBottom - pageTop));
canvas.Draw(PageOutlinePen, new RectangularPolygon(pageLeft, pageTop, pageRight - pageLeft, pageBottom - pageTop));
canvas.Fill(PageBrush, new RectanglePolygon(pageLeft, pageTop, pageRight - pageLeft, pageBottom - pageTop));
canvas.Draw(PageOutlinePen, new RectanglePolygon(pageLeft, pageTop, pageRight - pageLeft, pageBottom - pageTop));
canvas.Fill(ObstacleBrush, obstaclePath);
canvas.Draw(ObstacleOutlinePen, obstaclePath);

Expand Down Expand Up @@ -238,7 +238,7 @@ public override void Paint(DrawingCanvas canvas, TimeSpan deltaTime)
// The translucent slot fill is a visual aid for the sample. It
// makes the row splitting visible so readers can compare the
// available rectangles with the selected obstacle shape.
canvas.Fill(SlotBrush, new RectangularPolygon(slot.Left, y, slotWidth, lineHeight));
canvas.Fill(SlotBrush, new RectanglePolygon(slot.Left, y, slotWidth, lineHeight));
canvas.DrawText(line, new PointF(slot.Left, y), TextBrush, pen: null);

rowHeight = MathF.Max(rowHeight, lineHeight);
Expand Down Expand Up @@ -274,14 +274,14 @@ private IPath CreateObstaclePath(PointF center, float size)
// circle or rectangle math.
return this.ObstacleShape switch
{
ManualTextFlowObstacleShape.Rectangle => new RectangularPolygon(
ManualTextFlowObstacleShape.Rectangle => new RectanglePolygon(
center.X - radius,
center.Y - radius,
size,
size),
ManualTextFlowObstacleShape.Triangle => new RegularPolygon(center, 3, radius, 180F),
ManualTextFlowObstacleShape.Diamond => new RegularPolygon(center, 4, radius, 0F),
ManualTextFlowObstacleShape.Star => new Star(center, 5, radius * .45F, radius, -18F),
ManualTextFlowObstacleShape.Star => new StarPolygon(center, 5, radius * .45F, radius, -18F),
_ => new EllipsePolygon(center, new SizeF(size, size))
};
}
Expand Down Expand Up @@ -583,7 +583,7 @@ internal enum ManualTextFlowObstacleShape
Circle,

/// <summary>
/// A rectangular obstacle backed by <see cref="RectangularPolygon"/>.
/// A rectangular obstacle backed by <see cref="RectanglePolygon"/>.
/// </summary>
Rectangle,

Expand All @@ -598,7 +598,7 @@ internal enum ManualTextFlowObstacleShape
Diamond,

/// <summary>
/// A concave star obstacle backed by <see cref="Star"/>.
/// A concave star obstacle backed by <see cref="StarPolygon"/>.
/// </summary>
Star
}
10 changes: 5 additions & 5 deletions samples/WebGPUExternalSurfaceDemo/Scenes/RichTextEditorScene.cs
Original file line number Diff line number Diff line change
Expand Up @@ -209,10 +209,10 @@ public override void Paint(DrawingCanvas canvas, TimeSpan deltaTime)
}

canvas.Fill(BackgroundBrush, canvas.Bounds);
canvas.Fill(EditorBrush, new RectangularPolygon(editorBounds));
canvas.Draw(BorderPen, new RectangularPolygon(editorBounds));
canvas.Fill(EditorBrush, new RectanglePolygon(editorBounds));
canvas.Draw(BorderPen, new RectanglePolygon(editorBounds));

IPath editorClip = new RectangularPolygon(editorBounds);
IPath editorClip = new RectanglePolygon(editorBounds);

// Selection is painted before glyphs, matching normal editor behavior.
// The clipping scope applies only to text so the editor chrome remains crisp.
Expand Down Expand Up @@ -549,11 +549,11 @@ private void DrawSelection(DrawingCanvas canvas, TextMetrics metrics)
// That keeps mixed-bidi ranges visually split instead of filling across reordered gaps.
canvas.Fill(
SelectionBrush,
new RectangularPolygon(rectangle.X, rectangle.Y, width, height));
new RectanglePolygon(rectangle.X, rectangle.Y, width, height));

canvas.Draw(
SelectionBorderPen,
new RectangularPolygon(rectangle.X, rectangle.Y, width, height));
new RectanglePolygon(rectangle.X, rectangle.Y, width, height));
}
}

Expand Down
77 changes: 73 additions & 4 deletions src/ImageSharp.Drawing/PathBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ public PathBuilder AddArc(float x, float y, float radiusX, float radiusY, float
/// <summary>
/// Adds a pie sector to the current path as a closed figure.
/// </summary>
/// <param name="center">The center point of the pie.</param>
/// <param name="center">The center point of the pie sector.</param>
/// <param name="radius">The x and y radii of the pie ellipse.</param>
/// <param name="rotation">The ellipse rotation in degrees.</param>
/// <param name="startAngle">The pie start angle in degrees.</param>
Expand All @@ -400,7 +400,7 @@ public PathBuilder AddPie(PointF center, SizeF radius, float rotation, float sta
{
_ = this.StartFigure();

foreach (ILineSegment segment in new Pie(center, radius, rotation, startAngle, sweepAngle).LineSegments)
foreach (ILineSegment segment in new PiePolygon(center, radius, rotation, startAngle, sweepAngle).LineSegments)
{
_ = this.AddSegment(segment);
}
Expand All @@ -411,7 +411,7 @@ public PathBuilder AddPie(PointF center, SizeF radius, float rotation, float sta
/// <summary>
/// Adds a pie sector to the current path as a closed figure.
/// </summary>
/// <param name="center">The center point of the pie.</param>
/// <param name="center">The center point of the pie sector.</param>
/// <param name="radius">The x and y radii of the pie ellipse.</param>
/// <param name="startAngle">The pie start angle in degrees.</param>
/// <param name="sweepAngle">The pie sweep angle in degrees.</param>
Expand Down Expand Up @@ -477,6 +477,75 @@ public PathBuilder AddRectangle(float x, float y, float width, float height)
new PointF(x + width, y + height),
new PointF(x, y + height));

/// <summary>
/// Adds a rounded rectangle to the current path as a closed figure.
/// </summary>
/// <param name="rectangle">The rectangle bounds.</param>
/// <param name="radius">The x and y radius of each corner.</param>
/// <returns>The <see cref="PathBuilder"/>.</returns>
public PathBuilder AddRoundedRectangle(RectangleF rectangle, float radius)
=> this.AddRoundedRectangle(rectangle, new SizeF(radius, radius));

/// <summary>
/// Adds a rounded rectangle to the current path as a closed figure.
/// </summary>
/// <param name="rectangle">The rectangle bounds.</param>
/// <param name="radius">The x and y radii of each corner.</param>
/// <returns>The <see cref="PathBuilder"/>.</returns>
public PathBuilder AddRoundedRectangle(RectangleF rectangle, SizeF radius)
{
_ = this.StartFigure();

foreach (ILineSegment segment in new RoundedRectanglePolygon(rectangle, radius).LineSegments)
{
_ = this.AddSegment(segment);
}

return this.CloseFigure();
}

/// <summary>
/// Adds a rounded rectangle to the current path as a closed figure.
/// </summary>
/// <param name="rectangle">The rectangle bounds.</param>
/// <param name="radius">The x and y radius of each corner.</param>
/// <returns>The <see cref="PathBuilder"/>.</returns>
public PathBuilder AddRoundedRectangle(Rectangle rectangle, float radius)
=> this.AddRoundedRectangle((RectangleF)rectangle, radius);

/// <summary>
/// Adds a rounded rectangle to the current path as a closed figure.
/// </summary>
/// <param name="rectangle">The rectangle bounds.</param>
/// <param name="radius">The x and y radii of each corner.</param>
/// <returns>The <see cref="PathBuilder"/>.</returns>
public PathBuilder AddRoundedRectangle(Rectangle rectangle, SizeF radius)
=> this.AddRoundedRectangle((RectangleF)rectangle, radius);

/// <summary>
/// Adds a rounded rectangle to the current path as a closed figure.
/// </summary>
/// <param name="x">The x-coordinate of the rectangle.</param>
/// <param name="y">The y-coordinate of the rectangle.</param>
/// <param name="width">The rectangle width.</param>
/// <param name="height">The rectangle height.</param>
/// <param name="radius">The x and y radius of each corner.</param>
/// <returns>The <see cref="PathBuilder"/>.</returns>
public PathBuilder AddRoundedRectangle(float x, float y, float width, float height, float radius)
=> this.AddRoundedRectangle(new RectangleF(x, y, width, height), radius);

/// <summary>
/// Adds a rounded rectangle to the current path as a closed figure.
/// </summary>
/// <param name="x">The x-coordinate of the rectangle.</param>
/// <param name="y">The y-coordinate of the rectangle.</param>
/// <param name="width">The rectangle width.</param>
/// <param name="height">The rectangle height.</param>
/// <param name="radius">The x and y radii of each corner.</param>
/// <returns>The <see cref="PathBuilder"/>.</returns>
public PathBuilder AddRoundedRectangle(float x, float y, float width, float height, SizeF radius)
=> this.AddRoundedRectangle(new RectangleF(x, y, width, height), radius);

/// <summary>
/// Adds a polygon to the current path as a closed figure.
/// </summary>
Expand Down Expand Up @@ -579,7 +648,7 @@ public PathBuilder AddStar(PointF center, int prongs, float innerRadii, float ou
{
_ = this.StartFigure();

foreach (ILineSegment segment in new Star(center, prongs, innerRadii, outerRadii, angle).LineSegments)
foreach (ILineSegment segment in new StarPolygon(center, prongs, innerRadii, outerRadii, angle).LineSegments)
{
_ = this.AddSegment(segment);
}
Expand Down
Loading
Loading