SvgMergedShapes.cs
- //
- // This code is part of Document Solutions for Imaging demos.
- // Copyright (c) MESCIUS inc. All rights reserved.
- //
- using System;
- using System.IO;
- using System.Drawing;
- using System.Collections.Generic;
- using System.Linq;
- using System.Numerics;
- using GrapeCity.Documents.Drawing;
- using GrapeCity.Documents.Text;
- using GrapeCity.Documents.Imaging;
- using GrapeCity.Documents.Svg;
- using DsImagingWeb.Demos.Common;
- using System.Xml;
-
- namespace DsImagingWeb.Demos
- {
- // This example shows how to combine SVG elements to create clipping paths
- // that are used to effectively merge geometric figures.
- // Parts of the image are associated with SVG title elements which show
- // as tooltips if the SVG is displayed in a browser.
- public class SvgMergedShapes
- {
- public string DefaultMime { get => Common.Util.MimeTypes.SVG; }
-
- public Stream GenerateImageStream(string targetMime, Size pixelSize, float dpi, bool opaque, string[] sampleParams = null)
- {
- if (targetMime != Common.Util.MimeTypes.SVG)
- throw new Exception("This sample only supports SVG output format.");
-
- using var svgDoc = new GcSvgDocument();
- var svg = svgDoc.RootSvg;
- var items = svg.Children;
-
- var width = new SvgLength(pixelSize.Width);
- var height = new SvgLength(pixelSize.Height);
-
- svg.Width = width;
- svg.Height = height;
-
- // Root title:
- var title = new SvgTitleElement();
- items.Add(title);
- title.Children.Add(new SvgContentElement(XmlNodeType.Text)
- {
- Content = "Root SVG Title"
- });
- // Root bounds:
- var bounds = new SvgRectElement()
- {
- X = new SvgLength(0),
- Y = new SvgLength(0),
- Width = width,
- Height = height,
- Stroke = new SvgPaint(new SvgColor(Color.DarkBlue)),
- Fill = new SvgPaint(new SvgColor(Color.DarkSeaGreen)),
- };
- items.Add(bounds);
-
- // Geometry:
- float
- centerX = 200,
- centerY = 200,
- radius = 190,
- polyWidth = 180,
- polyHeight = 320,
- polyD = 30,
- pad = 10;
-
- // We add an outer group to hold everything else,
- // so that it can be easily positioned within the overall bounds:
- var outerGroup = new SvgGroupElement();
- items.Add(outerGroup);
- items = outerGroup.Children;
- // Center the group:
- var outerGroupTranslateX = new SvgLength(pixelSize.Width / 2 - centerX);
- var outerGroupTranslateY = new SvgLength(pixelSize.Height / 2 - centerY - polyHeight / 2);
- outerGroup.Transform = new List<SvgTransform>()
- {
- new SvgTranslateTransform() { TranslateX = outerGroupTranslateX, TranslateY = outerGroupTranslateY },
- };
-
- // Add a 'defs' element containing clipPath elements
- // that will be used to merge various geometric figures
- // to provide a complex clipping path:
- var defs = new SvgDefsElement();
- items.Add(defs);
-
- // Create the outer clip built by adding a circle and a polygon
- // resembling an inverted keystone, so that the union of the two figures
- // looks like a keyhole:
- var clipPathOuter = new SvgClipPathElement() { ID = "outerClip" };
- defs.Children.Add(clipPathOuter);
- clipPathOuter.Children.Add(new SvgCircleElement()
- {
- CenterX = new SvgLength(centerX),
- CenterY = new SvgLength(centerY),
- Radius = new SvgLength(radius)
- });
- clipPathOuter.Children.Add(new SvgPolygonElement()
- {
- Points = new List<SvgPoint>()
- {
- new SvgPoint(new SvgLength(centerX - polyWidth / 2), new SvgLength(centerY + radius * 0.8f)),
- new SvgPoint(new SvgLength(centerX - polyWidth / 2 - polyD), new SvgLength(centerY + radius + polyHeight)),
- new SvgPoint(new SvgLength(centerX + polyWidth / 2 + polyD), new SvgLength(centerY + radius + polyHeight)),
- new SvgPoint(new SvgLength(centerX + polyWidth / 2), new SvgLength(centerY + radius * 0.8f)),
- }
- });
-
- // Create the inner clip by adding a smaller circle and a rectangle
- // that is smaller than the keystone polygon:
- var clipPathInner = new SvgClipPathElement() { ID = "innerClip" };
- defs.Children.Add(clipPathInner);
- clipPathInner.Children.Add(new SvgCircleElement()
- {
- CenterX = new SvgLength(centerX),
- CenterY = new SvgLength(centerY),
- Radius = new SvgLength(radius - pad)
- });
- clipPathInner.Children.Add(new SvgRectElement()
- {
- X = new SvgLength(centerX - polyWidth / 2 + pad),
- Y = new SvgLength(centerY + radius * 0.8f),
- Width = new SvgLength(polyWidth - pad * 2),
- Height = new SvgLength(polyHeight - pad * 2)
- });
-
- // A filled rectangle taking up the whole SVG area (100%x100%)
- // but clipped by the "outerClip" figure:
- var rcOuter = new SvgRectElement()
- {
- Width = new SvgLength(width.Value - outerGroupTranslateX.Value),
- Height = new SvgLength(height.Value - outerGroupTranslateY.Value),
- Fill = new SvgPaint(Color.DarkBlue),
- ClipPath = new SvgReference("outerClip")
- };
- items.Add(rcOuter);
- var descR = new SvgTitleElement();
- descR.Children.Add(new SvgContentElement(XmlNodeType.Text)
- {
- Content = "Title of the dark blue rectangle"
- });
- rcOuter.Children.Add(descR);
-
- // Group clipped by the "innerClip", this will contain
- // a yellow fill and a rotated semi-transparent raster image:
- var group = new SvgGroupElement()
- {
- ClipPath = new SvgReference("innerClip")
- };
- items.Add(group);
-
- // We add to the group clipped by "innerClip"
- // a filled rectangle taking up the whole area (100%x100%):
- var rcInner = new SvgRectElement()
- {
- Width = new SvgLength(width.Value - outerGroupTranslateX.Value),
- Height = new SvgLength(height.Value - outerGroupTranslateY.Value),
- Fill = new SvgPaint(Color.DarkOrange),
- };
- group.Children.Add(rcInner);
-
- var desc = new SvgTitleElement();
- rcInner.Children.Add(desc);
- desc.Children.Add(new SvgContentElement(XmlNodeType.Text)
- {
- Content = "Title of the dark orange rectangle"
- });
-
- // We also add to the group an image that is rotated
- // and drawn semi-transparently:
- var imagePath = Path.Combine("Resources", "Images", "colosseum-resized.jpg");
- var bmp = new GcBitmap(imagePath);
-
- var imgTranslateX = new SvgLength(188);
- var imgTranslateY = new SvgLength(-55);
-
- var img = new SvgImageElement()
- {
- Href = new SvgReference(bmp, true) { InJpegFormat = true },
- Width = new SvgLength(400),
- Height = new SvgLength(525),
- Transform = new List<SvgTransform>()
- {
- new SvgTranslateTransform() { TranslateX = imgTranslateX, TranslateY = imgTranslateY },
- new SvgRotateTransform() { Angle = new SvgAngle(30) }
- },
- Opacity = 0.8f,
- };
- group.Children.Add(img);
-
- var descImg = new SvgTitleElement();
- img.Children.Add(descImg);
- descImg.Children.Add(new SvgContentElement(XmlNodeType.Text)
- {
- Content = "Title of the image"
- });
-
- // Save SVG to the output Stream
- var ms = new MemoryStream();
- svgDoc.Save(ms, new XmlWriterSettings() { Indent = true });
- ms.Seek(0, SeekOrigin.Begin);
- return ms;
- }
- }
- }
-