''
'' This code is part of Document Solutions for Imaging demos.
'' Copyright (c) MESCIUS inc. All rights reserved.
''
Imports System
Imports System.IO
Imports System.Drawing
Imports System.Collections.Generic
Imports System.Linq
Imports System.Numerics
Imports GrapeCity.Documents.Drawing
Imports GrapeCity.Documents.Text
Imports GrapeCity.Documents.Imaging
Imports GrapeCity.Documents.Svg
Imports GCTEXT = GrapeCity.Documents.Text
Imports GCDRAW = GrapeCity.Documents.Drawing
'' This example shows how to create an SVG from scratch,
'' grouping visually related elements and assigning unique
'' HTML IDs to the groups, so that each group can be found
'' and manipulated from JavaScript code (e.g. some elements
'' of a drawing can be hidden or shown in JavaScript, etc).
'' This sample renders an arch similar to that in SvgGraphicsArch,
'' but assigns separate IDs to:
'' - the background;
'' - the arch drawing;
'' - measurements lines.
Public Class SvgGraphicsHtmlId
Public ReadOnly Property DefaultMime As String
Get
Return Util.MimeTypes.SVG
End Get
End Property
Public Function GenerateImageStream(
ByVal targetMime As String,
ByVal pixelSize As Size,
ByVal dpi As Single,
ByVal opaque As Boolean,
Optional ByVal sampleParams As String() = Nothing) As Stream
If targetMime <> Util.MimeTypes.SVG Then
Throw New Exception("This sample only supports SVG output format.")
End If
Dim background As Color = Color.PaleGoldenrod,
line As Color = Color.FromArgb(11, 83, 69),
arc As Color = Color.FromArgb(22, 160, 133),
fill As Color = Color.FromArgb(255, 171, 145),
marks As Color = Color.DarkGray,
text As Color = Color.Black,
textBack As Color = Color.Cornsilk
Dim Inch = dpi
'' Text format for labels:
Dim tf = New TextFormat() With {
.Font = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "FreeSerif.ttf")),
.FontSize = Inch / 6,
.ForeColor = text
}
'' Arc bounding rectangle:
Dim rc = New RectangleF(0, 0, Inch * 4, Inch * 4.8F)
'' Transform to center the drawing:
Dim transform = Matrix3x2.CreateTranslation(pixelSize.Width / 2.0F - rc.Width / 2, pixelSize.Height / 2.0F - rc.Height / 2)
'' A document for each layer:
Dim svgs = New List(Of GcSvgDocument)()
'' In a loop (from 0 to 2), draw content that belongs to the desired
'' current layer on a graphics, then convert that graphics to a temp GcSvgDocument
'' and save it in a list:
For i As Integer = 0 To 2
Using g As New GcSvgGraphics(pixelSize.Width, pixelSize.Height)
If i = 0 Then
'' Background:
g.FillRectangle(New RectangleF(0, 0, g.Width, g.Height), background)
ElseIf i = 1 Then
'' Arch and text label:
g.Transform = transform
DrawArch(g, rc, rc.Height * 0.3F, rc.Width * 0.08F, line, arc, fill)
g.DrawString("ARCH", tf, rc, TextAlignment.Center, ParagraphAlignment.Center, False)
g.Transform = Matrix3x2.Identity
ElseIf i = 2 Then
'' Measurement lines:
g.Transform = transform
Dim w = Inch / 8
Dim pen = New GCDRAW.Pen(marks)
'' Width line/label:
Dim txt = $"{(rc.Width / Inch):F}"""
Dim s = g.MeasureString(txt, tf)
Dim d = s.Height * 1.5F
g.DrawLine(rc.Left, rc.Top - d, rc.Right, rc.Top - d, pen)
g.DrawLine(rc.Left, rc.Top - d, rc.Left + w, rc.Top - d - w, pen)
g.DrawLine(rc.Left, rc.Top - d, rc.Left + w, rc.Top - d + w, pen)
g.DrawLine(rc.Right, rc.Top - d, rc.Right - w, rc.Top - d - w, pen)
g.DrawLine(rc.Right, rc.Top - d, rc.Right - w, rc.Top - d + w, pen)
Dim rcTxt = New RectangleF(rc.Left + rc.Width / 2 - s.Width / 2, rc.Top - d - s.Height / 2, s.Width, s.Height)
rcTxt.Inflate(2, 2)
g.FillRectangle(rcTxt, textBack)
g.DrawString(txt, tf, rcTxt, TextAlignment.Center, ParagraphAlignment.Center, False)
'' Height line/label:
txt = $"{(rc.Height / Inch):F}"""
s = g.MeasureString(txt, tf)
d = s.Width
g.DrawLine(rc.Left - d, rc.Top, rc.Left - d, rc.Bottom, pen)
g.DrawLine(rc.Left - d, rc.Top, rc.Left - d - w, rc.Top + w, pen)
g.DrawLine(rc.Left - d, rc.Top, rc.Left - d + w, rc.Top + w, pen)
g.DrawLine(rc.Left - d, rc.Bottom, rc.Left - d - w, rc.Bottom - w, pen)
g.DrawLine(rc.Left - d, rc.Bottom, rc.Left - d + w, rc.Bottom - w, pen)
rcTxt = New RectangleF(rc.Left - d - s.Width / 2, rc.Top + rc.Height / 2 - s.Height / 2, s.Width, s.Height)
rcTxt.Inflate(2, 2)
g.FillRectangle(rcTxt, textBack)
g.DrawString(txt, tf, rcTxt, TextAlignment.Center, ParagraphAlignment.Center, False)
g.Transform = Matrix3x2.Identity
End If
'' Convert the layer to a GcSvgDocument and add it to the list:
svgs.Add(g.ToSvgDocument())
End Using
Next
'' Create the resulting SVG, add each of the temp documents
'' into a separate group with unique ID that can be used
'' to find and manipulate it:
Dim svg = New GcSvgDocument()
For i As Integer = 0 To svgs.Count - 1
Dim tsvg = svgs(i)
Dim group = New SvgGroupElement() With {
.ID = $"myId{i}"
}
While tsvg.RootSvg.Children.Count > 0
Dim e = tsvg.RootSvg.Children(0)
tsvg.RootSvg.Children.RemoveAt(0)
group.Children.Add(e)
End While
svg.RootSvg.Children.Add(group)
Next
svg.RootSvg.ViewBox = New SvgViewBox(0, 0, pixelSize.Width, pixelSize.Height)
Dim ms = New MemoryStream()
svg.Save(ms)
ms.Seek(0, SeekOrigin.Begin)
Return ms
End Function
Private Sub DrawArch(g As GcGraphics, rc As RectangleF, harc As Single, wd As Single, line As Color, arch As Color, fill As Color)
Dim path = g.CreatePath()
'' Insides filler (start from bottom left, to clockwise):
path.BeginFigure(rc.Left + wd, rc.Bottom - wd)
path.AddLine(rc.Left + wd, rc.Top + harc)
path.AddArc(New ArcSegment() With {
.ArcSize = ArcSize.Small,
.Point = New PointF(rc.Right - wd, rc.Top + harc),
.RotationAngle = 0,
.Size = New SizeF(rc.Width / 2.0F - wd, harc - wd),
.SweepDirection = SweepDirection.Clockwise
})
path.AddLine(rc.Right - wd, rc.Bottom - wd)
path.EndFigure(FigureEnd.Closed)
g.FillPath(path, fill)
path.Dispose()
'' Arc outlines (start from bottom left, to clockwise):
path = g.CreatePath()
path.BeginFigure(rc.Left, rc.Bottom)
path.AddLine(rc.Left, rc.Top + harc)
path.AddLine(rc.Left + wd, rc.Top + harc)
path.AddLine(rc.Left + wd, rc.Bottom - wd)
path.EndFigure(FigureEnd.Closed)
path.BeginFigure(rc.Left, rc.Top + harc)
path.AddArc(New ArcSegment() With {
.ArcSize = ArcSize.Small,
.Point = New PointF(rc.Right, rc.Top + harc),
.RotationAngle = 0,
.Size = New SizeF(rc.Width / 2.0F, harc),
.SweepDirection = SweepDirection.Clockwise
})
path.AddLine(rc.Right - wd, rc.Top + harc)
path.AddArc(New ArcSegment() With {
.ArcSize = ArcSize.Small,
.Point = New PointF(rc.Left + wd, rc.Top + harc),
.RotationAngle = 0,
.Size = New SizeF(rc.Width / 2.0F - wd, harc - wd),
.SweepDirection = SweepDirection.CounterClockwise
})
path.EndFigure(FigureEnd.Closed)
path.BeginFigure(rc.Right, rc.Top + harc)
path.AddLine(rc.Right, rc.Bottom)
path.AddLine(rc.Right - wd, rc.Bottom - wd)
path.AddLine(rc.Right - wd, rc.Top + harc)
path.EndFigure(FigureEnd.Closed)
path.BeginFigure(rc.Right, rc.Bottom)
path.AddLine(rc.Left, rc.Bottom)
path.AddLine(rc.Left + wd, rc.Bottom - wd)
path.AddLine(rc.Right - wd, rc.Bottom - wd)
path.EndFigure(FigureEnd.Closed)
g.FillPath(path, arch)
g.DrawPath(path, New GCDRAW.Pen(line, 2))
path.Dispose()
End Sub
End Class