'''' This code is part of Document Solutions for Imaging demos.'' Copyright (c) MESCIUS inc. All rights reserved.''ImportsSystemImportsSystem.IOImportsSystem.DrawingImportsSystem.Collections.GenericImportsSystem.LinqImportsSystem.NumericsImportsSystem.XmlImportsGrapeCity.Documents.ImagingImportsGrapeCity.Documents.Svg '' 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.PublicClassSvgMergedShapesPublicReadOnlyPropertyDefaultMimeAsStringGetReturn Util.MimeTypes.SVGEndGetEndProperty PublicFunctionGenerateImageStream(ByVal targetMime AsString,ByVal pixelSize AsSize,ByVal dpi AsSingle,ByVal opaque AsBoolean,OptionalByVal sampleParams AsString() = Nothing) AsStream If targetMime <> Util.MimeTypes.SVG ThenThrowNewException("This sample only supports SVG output format.")EndIf Using svgDoc AsNewGcSvgDocument()Dim svg = svgDoc.RootSvgDim items = svg.Children Dim width = NewSvgLength(pixelSize.Width)Dim height = NewSvgLength(pixelSize.Height) svg.Width = width svg.Height = height '' Root title:Dim title = NewSvgTitleElement() items.Add(title) title.Children.Add(NewSvgContentElement(XmlNodeType.Text) With { .Content = "Root SVG Title" }) '' Root bounds:Dim bounds = NewSvgRectElement() With { .X = NewSvgLength(0), .Y = NewSvgLength(0), .Width = width, .Height = height, .Stroke = NewSvgPaint(NewSvgColor(Color.DarkBlue)), .Fill = NewSvgPaint(NewSvgColor(Color.DarkSeaGreen)) } items.Add(bounds) '' Geometry:Dim centerX AsSingle = 200.0FDim centerY AsSingle = 200.0FDim radius AsSingle = 190.0FDim polyWidth AsSingle = 180.0FDim polyHeight AsSingle = 320.0FDim polyD AsSingle = 30.0FDim pad AsSingle = 10.0F '' We add an outer group to hold everything else,'' so that it can be easily positioned within the overall bounds:Dim outerGroup = NewSvgGroupElement() items.Add(outerGroup) items = outerGroup.Children '' Center the group:Dim outerGroupTranslateX = NewSvgLength(pixelSize.Width / 2.0F - centerX)Dim outerGroupTranslateY = NewSvgLength(pixelSize.Height / 2.0F - centerY - polyHeight / 2.0F) outerGroup.Transform = NewList(OfSvgTransform) From {NewSvgTranslateTransform() With {.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:Dim defs = NewSvgDefsElement() 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:Dim clipPathOuter = NewSvgClipPathElement() With {.ID = "outerClip"} defs.Children.Add(clipPathOuter) clipPathOuter.Children.Add(NewSvgCircleElement() With { .CenterX = NewSvgLength(centerX), .CenterY = NewSvgLength(centerY), .Radius = NewSvgLength(radius) }) clipPathOuter.Children.Add(NewSvgPolygonElement() With { .Points = NewList(OfSvgPoint) From {NewSvgPoint(NewSvgLength(centerX - polyWidth / 2.0F), NewSvgLength(centerY + radius * 0.8F)),NewSvgPoint(NewSvgLength(centerX - polyWidth / 2.0F - polyD), NewSvgLength(centerY + radius + polyHeight)),NewSvgPoint(NewSvgLength(centerX + polyWidth / 2.0F + polyD), NewSvgLength(centerY + radius + polyHeight)),NewSvgPoint(NewSvgLength(centerX + polyWidth / 2.0F), NewSvgLength(centerY + radius * 0.8F)) } }) '' Create the inner clip by adding a smaller circle and a rectangle'' that is smaller than the keystone polygon:Dim clipPathInner = NewSvgClipPathElement() With {.ID = "innerClip"} defs.Children.Add(clipPathInner) clipPathInner.Children.Add(NewSvgCircleElement() With { .CenterX = NewSvgLength(centerX), .CenterY = NewSvgLength(centerY), .Radius = NewSvgLength(radius - pad) }) clipPathInner.Children.Add(NewSvgRectElement() With { .X = NewSvgLength(centerX - polyWidth / 2.0F + pad), .Y = NewSvgLength(centerY + radius * 0.8F), .Width = NewSvgLength(polyWidth - pad * 2.0F), .Height = NewSvgLength(polyHeight - pad * 2.0F) }) '' A filled rectangle taking up the whole SVG area (100%x100%)'' but clipped by the "outerClip" figure:Dim rcOuter = NewSvgRectElement() With { .Width = NewSvgLength(width.Value - outerGroupTranslateX.Value), .Height = NewSvgLength(height.Value - outerGroupTranslateY.Value), .Fill = NewSvgPaint(Color.DarkBlue), .ClipPath = NewSvgReference("outerClip") } items.Add(rcOuter)Dim descR = NewSvgTitleElement() descR.Children.Add(NewSvgContentElement(XmlNodeType.Text) With { .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:Dim groupEl = NewSvgGroupElement() With { .ClipPath = NewSvgReference("innerClip") } items.Add(groupEl) '' We add to the group clipped by "innerClip"'' a filled rectangle taking up the whole area (100%x100%):Dim rcInner = NewSvgRectElement() With { .Width = NewSvgLength(width.Value - outerGroupTranslateX.Value), .Height = NewSvgLength(height.Value - outerGroupTranslateY.Value), .Fill = NewSvgPaint(Color.DarkOrange) } groupEl.Children.Add(rcInner) Dim desc = NewSvgTitleElement() rcInner.Children.Add(desc) desc.Children.Add(NewSvgContentElement(XmlNodeType.Text) With { .Content = "Title of the dark orange rectangle" }) '' We also add to the group an image that is rotated'' and drawn semi-transparently:Dim imagePath = Path.Combine("Resources", "Images", "colosseum-resized.jpg")Dim bmp = NewGcBitmap(imagePath) Dim imgTranslateX = NewSvgLength(188)Dim imgTranslateY = NewSvgLength(-55) Dim img = NewSvgImageElement() With { .Href = NewSvgReference(bmp, True) With {.InJpegFormat = True}, .Width = NewSvgLength(400), .Height = NewSvgLength(525), .Transform = NewList(OfSvgTransform) From {NewSvgTranslateTransform() With {.TranslateX = imgTranslateX, .TranslateY = imgTranslateY},NewSvgRotateTransform() With {.Angle = NewSvgAngle(30)} }, .Opacity = 0.8F } groupEl.Children.Add(img) Dim descImg = NewSvgTitleElement() img.Children.Add(descImg) descImg.Children.Add(NewSvgContentElement(XmlNodeType.Text) With { .Content = "Title of the image" }) '' Save SVG to the output StreamDim ms AsNewMemoryStream() svgDoc.Save(ms, NewXmlWriterSettings() With {.Indent = True}) ms.Seek(0, SeekOrigin.Begin)Return msEndUsingEndFunctionEndClass