Advanced SVG Creation and Modification with Aspose.SVG Builder API – C#

Efficient SVG Management with Aspose.SVG’s Builder API

Explore the Aspose.SVG Builder API is designed for streamlined creation and updating of SVG elements in C#.

This article explores the capabilities of the Aspose.SVG Builder API to create and modify SVG elements in C#. You will see the efficiency of Fluent Builder Pattern and mixins in SVG manipulation. You will learn about the SVGElementBuilder class, its specialized builders, and how they simplify SVG programming.

Rationale Behind the SVG Builder

In the realm of web and graphic development, managing Scalable Vector Graphics (SVG) can be a complex task, demanding a balance between precision and efficiency. The Aspose.SVG SVG Builder API has been developed to address this challenge, offering developers a powerful tool for creating and updating SVG elements in a streamlined manner.

The development of the SVG builder was motivated by several key factors:

To achieve these objectives, the Aspose.SVG SVG Builder API employs the Fluent Builder Pattern, a design methodology that aligns perfectly with the need for simplicity, clarity, and versatility in SVG manipulation.

Element Builders in Aspose.SVG: Streamlining SVG Creation and Modification

In the Aspose.SVG Builder API, all element builders, such as SVGSVGElementBuilder, SVGGElementBuilder, and others, inherit from the core SVGElementBuilder class. This inheritance structure streamlines the process of creating and modifying SVG elements, ensuring consistency and efficiency across different types of elements.

Creating New Elements

Element builders provide a Build(Document document) method, enabling the creation of new SVG elements and their addition to an SVG document.

Example: Creation of New SVG Elements:

 1using (var document = new SVGDocument())
 2{
 3    // Create a new <g> (group) element using SVGGElementBuilder
 4    var gElement = new SVGGElementBuilder()
 5        // Additional element configurations
 6        // ...
 7        .Build(document);
 8    // Append the newly created <g> element to the root <svg> element
 9    document.RootElement.AppendChild(gElement);
10}

In this example, SVGGElementBuilder is used to create a new group <g> element. The Build() method generates the element, which is then appended to the root <svg> element.

Modifying Existing Elements

Element builders also offer a Build(T element) method for updating existing SVG elements, allowing modifications to their attributes or styles.

Example: Update of SVG Elements:

 1using (var document = new SVGDocument())
 2{
 3    // Assume an existing SVG element is part of the document
 4    var existingSvgElement = document.FirstChild as SVGSVGElement;
 5
 6    // Update the existing SVG element using SVGSVGElementBuilder
 7    new SVGSVGElementBuilder()
 8        // Additional element configurations
 9        // ...
10        // The existingSvgElement is now updated with new configurations
11        .Build(existingSvgElement);
12}

In this example, SVGSVGElementBuilder is used to update an existing SVG element. The Build() method applies new configurations to the provided element, updating it within the SVG document.

You will find more C# examples of using Aspose.SVG Builder API to create and edit elements in the article Element Builders. You’ll learn about the SVGElementBuilder class, its specialized builders, and how they make SVG programming easier.

Understanding Fluent Builders

In the Aspose.SVG SVG Builder API, the Fluent Builder Pattern is employed to simplify the construction and updating of SVG elements, making the process intuitive and less prone to errors.

The essence of this pattern in the Aspose.SVG API is methods that configure an SVG element and then return the builder object. This design enables method chaining in a coherent, linear manner, which is particularly effective in reducing the complexity associated with creating and manipulating SVG elements.

Within this context, lambda expressions are used to enhance the clarity and conciseness of the builder’s configuration methods. Lambda expressions allow for a detailed yet compact way of defining the attributes and styles of SVG elements. For instance, when adding a circle element, a lambda expression provides an inline, readable configuration:

1var svgElement = new SVGSVGElementBuilder()
2    .AddCircle(circle => circle
3        .Cx(50).Cy(50).R(20)
4        .Fill(Color.Blue).Stroke(Paint.None)
5        .StrokeWidth(2))
6    .Build();

Here, circle => circle.Cx(50).Cy(50).R(20).Fill(Color.Blue).Stroke(Paint.None).StrokeWidth(2) is a succinct way to configure the circle’s properties, such as its center, radius, fill, and stroke. This approach not only simplifies the element configuration but also enhances the code’s readability and maintainability.

Implementing Fluent Builder Pattern Using Mixins

In the Aspose.SVG SVG Builder API, the Fluent Builder Pattern is further enhanced by the use of mixins.

Understanding Mixins

Mixins in object-oriented programming are a way to include additional properties or methods into a class. They allow for the combination and reuse of multiple behaviors or attributes without resorting to the traditional class hierarchy. This is particularly beneficial in scenarios where multiple objects share common functionalities, but don’t necessarily belong to the same class hierarchy.

Mixins in Aspose.SVG SVG Builder

The Aspose.SVG Builder employs mixins to create a flexible and modular approach to building SVG elements. By using interfaces as mixins, the API allows different aspects of an SVG element to be combined and customized as needed.

Example of Mixin Implementation:

Consider the following code snippet from the Aspose.SVG SVG Builder API:

 1public static partial class SVGBuilderExtensions
 2{
 3    public static TBuilder Id<TBuilder>(this TBuilder builder, string value)
 4        where TBuilder : ISVGElementBuilder, ICoreAttributeSetter
 5    {
 6        return builder.SetAttribute("id", value);
 7    }
 8}
 9
10public interface ICompositeAttributeSetter :
11    IConditionalProcessingAttributeSetter,
12    ICoreAttributeSetter,
13    IGlobalEventAttributeSetter,
14    IDocumentElementEventAttributeSetter,
15    IGraphicalEventAttributeSetter,
16    IPresentationAttributeSetter { }
17
18public class SVGAElementBuilder : SVGElementBuilder<SVGAElement>,
19    ICompositeElementBuilder,
20    ICompositeAttributeSetter
21{
22    // Example usage
23    .AddA(a => a.Id("one"))
24}

In this example, SVGBuilderExtensions defines an extension method Id that sets the id attribute of an SVG element. The TBuilder type parameter is constrained to types that implement both ISVGElementBuilder and ICompositeAttributeSetter. This approach allows for a high level of customization and flexibility, as ICompositeAttributeSetter itself is a mixin composed of various attribute-setting interfaces.

Syntax Sugar in SVG Builder API: Enhancing Elegance and Efficiency

The Aspose.SVG SVG Builder API introduces syntax sugar to further refine the process of SVG creation and manipulation. This includes nested builders for various SVG elements, providing a more intuitive and efficient way to define complex SVG structures.

Builders within Builders


Path Builder (PathBuilder Class)

The PathBuilder class offers a nuanced way of creating SVG <path> elements. It allows for defining intricate paths using fluent syntax:

 1.AddPath(p => p
 2    // 'D' method defines the 'd' attribute, which contains the path data.
 3    .D(d => d
 4        // 'M' sets the starting point of the path (Move to x=5, y=0).
 5        .M(5, 0)
 6        // 'L' draws a line from the current point to the new point (Line to x=10, y=10).
 7        .L(10, 10)
 8        // Another 'L' to draw a line to a new point (Line to x=0, y=10).
 9        .L(0, 10)
10        // 'Z' closes the path by drawing a line to the starting point.
11        .Z())
12    // Sets the fill color of the path to blue and removes the stroke (border).
13    .Fill(Color.Blue).Stroke(pt => pt.None())
14)

In this example, the AddPath() method of the SVG builder is used to define a path element. The lambda expression passed to the D() method of PathBuilder class specifies the shape of the path using SVG path commands like M (move to), L (line to), and Z (close path).

Additionally, paths can be defined as strings, allowing for direct integration of SVG path data:

1.D(d => d.AddPathSegment("M199 89.3 C206.6 66.6 235.8 13.2 270 30.3 286.6 38.6 298.9 59.4 310 73.3 ..."))

You will find more C# examples of using Aspose.SVG Builder API to create and edit SVG <path> elements in the article Path Builder. The article showcases how the Path Builder offers an intuitive syntax for defining SVG paths programmatically, enabling developers to streamline the process of creating intricate shapes and curves.

Transform Builder (TransformBuilder Class)

The TransformBuilder class facilitates the application of transformations to SVG elements:

 1.AddG(g => g
 2    // 'Transform' method applies transformations to the group element.
 3    .Transform(t => t
 4        // 'Translate' moves the element by x=130 and y=40 units.
 5        .Translate(130, 40)
 6        // 'Scale' uniformly scales the element by a factor of 8.
 7        .Scale(8)
 8        // Another 'Scale' to adjust the scaling differently in x and y directions.
 9        .Scale(.2, .2)
10        // Final 'Translate' to move the element by x=-5 and y=-5 units.
11        .Translate(-5, -5)))

Here, multiple transformations like translation and scaling are chained together to manipulate a group element <g>.

Rule Builder (RuleBuilder Class)

The RuleBuilder class is instrumental in defining styles within SVG:

1.AddStyle(st => st
2    .Type("text/css")
3    .AddRule("@font-face", r => r
4        .Opacity(.5)
5        .FontFamily("FreeSansWoff")
6        .Attribute("src", "url(woffs/FreeSans.woff) format(\"woff\")")
7    )
8)

This example shows how to add a CSS rule for @font-face within the SVG.

In the article Rule Builder, you will find more C# examples of using Aspose.SVG Builder API to apply CSS-like rules to SVG elements. You will learn about RuleBuilder class that is used to dynamically build a string of CSS styles by setting various attributes and their values.

Paint Builder (PaintBuilder Class)

The PaintBuilder is used for specifying stroke and fill attributes:

1.AddPattern(p => p.Id("Pat3a")
2    .Rect(0, 0, 20, 20)
3    .PatternUnits(CoordinateUnits.UserSpaceOnUse)
4    .AddRect(r => r.Rect(0, 0, 10, 10).Fill(Color.FromArgb(0x99, 0x33, 0xdd)))
5    .AddRect(r => r.Rect(10, 0, 10, 10).Fill(Color.Green))
6    .AddRect(r => r.Rect(0, 10, 10, 10).Fill(Color.Blue))
7    .AddRect(r => r.Rect(10, 10, 10, 10).Fill(Color.Yellow))
8)
9.AddRect(r => r.Rect(20, 20, 440, 80).Fill(f => f.PaintServerId("Pat3a")))

In this example, a pattern is first defined using AddPattern, where various colored rectangles are combined to create a complex fill pattern. The pattern is given an identifier “Pat3a”. Subsequently, this pattern is applied to a rectangle element using the Fill() method with PaintServerId("Pat3a"), which references the previously defined pattern.

In the article Paint Builder, you will find more C# examples of using Aspose.SVG Builder API to configure the paint properties of SVG elements. You will learn about PaintBuilder class that is used to specify the value of the stroke or fill attributes for various SVG shapes and elements when filling them with any paint, pattern, or gradient.

Using Enums for Predefined Attribute Values

Enums play an important role in the Aspose.SVG Builder API. They provide predefined values for certain attributes, reducing the risk of errors due to misspelling and offering a convenient list of valid options. For instance:

 1[PublicAPI(TargetProduct.SVG)]
 2public enum CoordinateUnits
 3{
 4    [Description("userSpaceOnUse")]
 5    UserSpaceOnUse,
 6
 7    [Description("objectBoundingBox")]
 8    ObjectBoundingBox,
 9}
10
11// Using the enum in a builder
12.AddClipPath(cp => cp.Id("one")
13    .ClipPathUnits(CoordinateUnits.ObjectBoundingBox))

Here, the CoordinateUnits enum provides specific values for the clipPathUnits attribute, ensuring correct and standardized input.

Additional Example for Better Understanding of Using SVG Builders

To further illustrate the capabilities and versatility of the Aspose.SVG Builder API, let’s delve into some practical examples that showcase the advanced features and techniques for creating and manipulating SVG elements.

Creating a Filter

Here’s an example of creating a complex filter using the Aspose.SVG Builder API:

 1using (var document = new SVGDocument())
 2{
 3    var svg = new SVGSVGElementBuilder()
 4        .WithXlink()
 5        .Width(200).Height(200)
 6        .AddDefs(d => d
 7            // Defining a filter with the ID 'spotlight'
 8            .AddFilter(f => f.Id("spotlight")
 9                // Adding an feImage, a filter primitive used for image processing
10                .AddFeImage(i => i
11                    .ColorInterpolationFilters(ColorInterpolation.SRGB)
12                    .Href("normal.png") // Source of the image
13                    .Result("img")) // Resultant image after applying filter
14                // Adding an feFlood, used to fill the filter subregion with a single color
15                .AddFeFlood(fl => fl
16                    .ColorInterpolationFilters(ColorInterpolation.SRGB)
17                    .Result("floodFill") // Resultant graphic of the flood fill
18                    .X(0).Y(0).Width(100, LengthType.Percentage).Height(100, LengthType.Percentage)
19                    .FloodColor(Color.FromArgb(0, 210, 2)).FloodOpacity(1))
20                // Adding an feBlend to blend the two previous results
21                .AddFeBlend(bl => bl
22                    .In("img").In2("floodFill") // Inputs to be blended
23                    .Mode(BlendMode.Color))) // Blend mode
24        )
25        // Applying the filter to a rectangle
26        .AddRect(r => r
27            .Rect(0, 0, 100, 100)
28            .Filter(fl => fl.FilterId("spotlight"))) // Reference to the defined filter
29        .Build(document.FirstChild as SVGSVGElement);
30}

In this code snippet, we define a filter spotlight that includes an image, a flood fill, and a blend effect. This filter is then applied to a rectangle element.

Creating Clipping and Masks

Creating clipping paths and masks allows you to control the visibility of certain parts of SVG elements. Here’s how it can be done:

 1using (var document = new SVGDocument())
 2{
 3    var svg = new SVGSVGElementBuilder()
 4        .Width(100, LengthType.Percentage).Height(100, LengthType.Percentage)
 5        .ViewBox(0, 0, 480, 360)
 6        .WithXlink()
 7        // ... additional setup ...
 8        .AddDefs(df => df
 9            // Defining a clipPath with ID 'one'
10            .AddClipPath(cp => cp.Id("one")
11                .ClipPathUnits(CoordinateUnits.ObjectBoundingBox)
12                // Adding circles to define the clipping area
13                .AddCircle(c => c.Cx(.3).Cy(.5).R(.2).Fill(p => p.None()).StrokeWidth(.15).Stroke(Color.Red))
14                .AddCircle(c => c.Cx(.7).Cy(.5).R(.2).Fill(p => p.None()).StrokeWidth(.15).Stroke(p => p.None())))
15            // Applying the clipPath to a rectangle
16            .AddRect(r => r.Rect(150, 0, 200, 200).Fill(Color.DarkBlue).ClipPath(p => p.ClipSourceId("one")))
17        )
18        .AddDefs(df => df
19            // Defining a mask with ID 'two'
20            .AddMask(m => m.Id("two")
21                .MaskUnits(CoordinateUnits.ObjectBoundingBox)
22                .MaskContentUnits(CoordinateUnits.ObjectBoundingBox)
23                .ColorInterpolation(ColorInterpolation.LinearRGB)
24                // Adding circles to define the mask area
25                .AddCircle(c => c.Cx(.3).Cy(.5).R(.2).Fill(Color.Blue).StrokeWidth(.15).Stroke(Color.Red))
26                .AddCircle(c => c.Cx(.7).Cy(.5).R(.2).Fill(Color.Blue).StrokeWidth(.15).Stroke(p => p.None())))
27            // Applying the mask to a rectangle
28            .AddRect(r => r.Rect(150, 150, 200, 200).Fill(Color.DarkBlue).Mask(p => p.MaskSourceId("two")))
29        )
30        .Build(document.FirstChild as SVGSVGElement);
31}

In this example, two SVG elements are created: one with a clipping path and another with a mask. Both the clipping path and the mask are defined using circles, which determine the visible area of the rectangles they are applied to.

Alternative Simplified Approach for SVG Element Creation

The Aspose.SVG Builder API also includes an alternative, simplified method for creating and adding SVG elements, offering efficiency and ease of use with default parameters.

Example of the Simplified SVG Builder API:

 1// Initialize an SVG document
 2using (var document = new SVGDocument())
 3{
 4    // Create an <svg> element with specified width, height and viewBox, and add into it other required elements
 5    var svg = new SVGSVGElementBuilder()
 6        .Width(100).Height(100)
 7        .ViewBox(-21, -21, 42, 42)
 8        .AddDefs(def => def
 9            .AddRadialGradient(id: "b", cx: .2, cy: .2, r: .5, fx: .2, fy: .2, extend: ev => ev
10                .AddStop(offset: 0, stopColor: Color.FromArgb(0xff, 0xff, 0xFF), stopOpacity: .7)
11                .AddStop(offset: 1, stopColor: Color.FromArgb(0xff, 0xff, 0xFF), stopOpacity: 0)
12            )
13            .AddRadialGradient(id: "a", cx: .5, cy: .5, r: .5, extend: ev => ev
14                .AddStop(offset: 0, stopColor: Color.FromArgb(0xff, 0xff, 0x00))
15                .AddStop(offset: .75, stopColor: Color.FromArgb(0xff, 0xff, 0x00))
16                .AddStop(offset: .95, stopColor: Color.FromArgb(0xee, 0xee, 0x00))
17                .AddStop(offset: 1, stopColor: Color.FromArgb(0xe8, 0xe8, 0x00))
18            )
19        )
20        .AddCircle(r: 20, fill: "url(#a)", stroke: Color.FromArgb(0, 0, 0), extend: c => c.StrokeWidth(.15))
21        .AddCircle(r: 20, fill: "b")
22        .AddG(g => g.Id("c")
23            .AddEllipse(cx: -6, cy: -7, rx: 2.5, ry: 4)
24            .AddPath(fill: Paint.None, stroke: Color.FromArgb(0, 0, 0), d: "M10.6 2.7a4 4 0 0 0 4 3", extend: e => e.StrokeWidth(.5).StrokeLineCap(StrokeLineCap.Round))
25        )
26        .AddUse(href: "#c", extend: e => e.Transform(t => t.Scale(-1, 1)))
27        .AddPath(d: "M-12 5a13.5 13.5 0 0 0 24 0 13 13 0 0 1-24 0", fill: Paint.None, stroke: Color.FromArgb(0, 0, 0), extend: e => e.StrokeWidth(.75))
28        .Build(document.FirstChild as SVGSVGElement);
29
30    // Save the SVG document
31    document.Save(Path.Combine(OutputDir, "face.svg"));
32}

In this example, the SVG Builder API is utilized to construct a comprehensive SVG structure using a more straightforward and efficient approach. The use of default parameters for common attributes like size, color, and position allows for rapid development of standard SVG elements, while still providing the option to customize as needed.

Aspose.SVG offers SVG Free Web Applications for converting SVG, JPG or PNG files, merging SVG files, image vectorizing, SVG sprite creating, SVG to base64 data encoding, and text vectorizing in SVG documents. These online Apps work on any operating system with a web browser and don’t require additional software installation. It’s a fast and easy way to efficiently and effectively solve your SVG-related tasks!

Subscribe to Aspose Product Updates

Get monthly newsletters & offers directly delivered to your mailbox.