Click here to Skip to main content
15,880,427 members
Articles / Desktop Programming / WPF

SVGImage Control

Rate me:
Please Sign up or sign in to vote.
4.89/5 (45 votes)
29 Jul 2010CPOL5 min read 345.8K   10.8K   141   40
A WPF control for showing SVG images.

svgimage_01.jpg

Introduction

SVG (Scalable Vector Graphic) is an XML based graphic format.

This little project started out as a simple SVG to XAML converter. I looked at some simple SVG files and noticed the similarity to XAML defined graphic, and decided to write a converter. However, I soon realized that SVG is a very complex format, and at the same time, I found no good reason for converting to XAML just to show the image on the screen, so instead, I started working on the SVG, SVGRender and the SVGImage classes.

  • The SVG class is the class that reads and parses the XML file.
  • SVGRender is the class that creates the WPF Drawing object based on the information from the SVG class.
  • SVGImage is the image control. The image control can either load the image from a filename - SetImage(filename) - or by setting the Drawing object through SetImage(Drawing), which allows multiple controls to share the same drawing instance.

The control only has a couple of properties, SizeType and ImageSource.

  • SizeType - controls how the image is stretched to fill the control
    • None: The image is not scaled. The image location is translated so the top left corner of the image bounding box is moved to the top left corner of the image control.
    • ContentToSizeNoStretch: The image is scaled to fit the control without any stretching. Either X or Y direction will be scaled to fill the entire width or height.
    • ContentToSizeStretch: The image will be stretched to fill the entire width and height.
    • SizeToContent: The control will be resized to fit the un-scaled image. If the image is larger than the max size for the control, the control is set to max size and the image is scaled.

    For None and ContentToSizeNoStretch, the Horizontal/VerticalContentAlignment properties can be used to position the image within the control.

  • ImageSource - This property is the same as SetImage(drawing), and is exposed to allow for the source to be set through binding.

The SVG format

Before writing any parser, it is a good idea to try and get a good understanding of the format you are going to parse, so I looked around for some documentation and came across this link which is the specification for SVG:

I also found this online book (also available for download in PDF format):

and this free SVG editor:

And after spending some time reading, I was ready to get started on the parser.

A quick walkthrough of the parsing

The main entry point is the SVG constructor (SVGReader.cs) which takes a filename. The only point of interest here is that I had to set the XmlResolver to null to avoid getting exceptions while reading different SVG files I found online.

C#
doc.XmlResolver = null; 

Each XML node is then parsed in the static method Group.AddToList (Shape.cs). Here, a new Shape object is created based on the XML tag, and the object itself is then passed the XML node to complete the parsing.

All basic shapes are implemented in Shapes.cs, while the more complex Path shape is implemented in PathShape.cs.

Finally, the actual WPF Drawing object is generated in the SVGRender class.

SVGRender.LoadGroup creates a single DrawingGroup object which contains a child group for each of the SVG shapes, where each shape is converted into a Geometry and then wrapped in a GeometryDrawing object to set the fill and stroke style.

That is pretty much it.

TSpan

7/29/2010 - added basic support for tspan in the text element.

Not all the different attributes supported by tspan are implemented, only font, style, and stroke/fill color.

Each tspan element can be thought of as an individual text element, complete with style, stroke, and fill attributes, and for this reason, it is derived from the base shape.

Parsing of a text with tspan elements is done in TextShape.ParseTSpan.

The rendering part is not designed for nested shapes (except for groups), but expect one shape, one geometry. TSpan is a bit different; each tspan element (even if nested) is added to the same GeometryGroup when the geometries are build. Each geometry can have different attributes which are the attributes on the tspan shape itself. Instead of redesigning how the SVGRender creates the drawing by iterating though the shapes, I chose to attach the tspan element (shape) itself directly to each of the build geometries using attached properties and then 'extract' the shape from the geometry when creating the drawing.

C#
if (shape is ClipArtViewer.TextShape)
{
       GeometryGroup gp = TextRender.BuildTextGeometry(shape as ClipArtViewer.TextShape);
       if (gp != null)
       {
              foreach (Geometry gm in gp.Children)
              {
                     TextShape.TSpan.Element tspan = TextRender.GetElement(gm);
                     if (tspan != null)
                           grp.Children.Add(NewDrawingItem(tspan, gm));
                     else
                           grp.Children.Add(NewDrawingItem(shape, gm));
              }
       }
}

Finally

The SVG parser and render is still not complete, but it is in a state where it can read most 'simple' SVG files I have found online so far. Of the chapters in the SVG Essentials book, the following chapters have been implemented:

  • Chapter 3 - Basic shapes
  • Chapter 5 - Transforming the coordinate system
  • Chapter 6 - Path
  • Chapter 7 - Patterns and gradients (only gradients is implemented)

I will continue working on this, and the next step is probably to add support for the text element.

Note! Some of the SVG files in the sample folder were found as free files online.

Revision history

  • 7/9/10 - Added support for <use> and <image> tags. Only internal groups can be referenced by <use>. The filename referenced by <image> must be relative to the current location of the CSV file. Examples 4.5, 4.6, and 4.8 from SVG Essentials have been added.
  • svgimage_02.jpg

  • 7/11/10 - Added support for simple text and formatting. Still missing support for word / letter spacing, tspan, text along a path, and other advanced format options.
  • svgimage_03.jpg

  • 7/13/10 - Uploaded new zip file with the TestForm file removed.
  • 7/18/10 - Added support for letter spacing and word spacing.
  • svgimage_04.jpg

    For text formatting, I had to use the low level GlyphRun, as FormattedText does not provide the same control over letter and word spacing.

    I added a new class TextRender.BuildTextGeometry (in TextRender.cs) which builds the geometry for the text using a GlyphRun example I found in this free eBook: http://books.google.com/books?id=558i6t1dKEAC&pg=PA485&source=gbs_toc_r&cad=4#v=onepage&q&f=false, with some slight modifications to fit my needs.

  • 7/29/2010
  • svgimage_05.jpg

    I finally got around to add basic support for tspan in the text element. Not all the different attributes supported by tspan are implemented, only font, style, and stroke/fill color.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionIf I try to use a background pattern, it does not display? Pin
mray3211-Feb-19 10:02
mray3211-Feb-19 10:02 
QuestionLicense - MIT or GNU Pin
amitergupta24-Sep-17 3:18
amitergupta24-Sep-17 3:18 
AnswerRe: License - MIT or GNU Pin
jogibear998819-Apr-18 19:15
jogibear998819-Apr-18 19:15 
QuestionThe same project in vb.net Pin
Member 1300579326-Feb-17 20:54
Member 1300579326-Feb-17 20:54 
BugSVG Images are renderized on black color Pin
CQüeb31-Aug-16 6:43
CQüeb31-Aug-16 6:43 
GeneralRe: SVG Images are renderized on black color Pin
CQüeb1-Sep-16 4:12
CQüeb1-Sep-16 4:12 
NewsSVG Pin
Member 1125218221-Nov-14 4:01
Member 1125218221-Nov-14 4:01 
QuestionFork at Github... Pin
jogibear998813-Dec-12 23:58
jogibear998813-Dec-12 23:58 
SuggestionSome minor changes Pin
wenzor19-Jan-12 7:16
wenzor19-Jan-12 7:16 
QuestionHow about separating SVG Library from Clipart Viewer? Pin
LastZolex6-Jan-11 21:30
LastZolex6-Jan-11 21:30 
GeneralBug Pin
Tomice27-Oct-10 10:29
Tomice27-Oct-10 10:29 
GeneralRe: Bug Pin
jkristia28-Oct-10 3:11
jkristia28-Oct-10 3:11 
QuestionCan I use SVGImage on WinForm? Pin
Vikram Lele23-Sep-10 1:27
Vikram Lele23-Sep-10 1:27 
AnswerRe: Can I use SVGImage on WinForm? Pin
jkristia23-Sep-10 3:08
jkristia23-Sep-10 3:08 
GeneralRe: Can I use SVGImage on WinForm? Pin
Vikram Lele23-Sep-10 18:09
Vikram Lele23-Sep-10 18:09 
GeneralNice! Pin
reflex@codeproject29-Jul-10 10:34
reflex@codeproject29-Jul-10 10:34 
GeneralSave as Image / BitmapImage Pin
ElGuroProgramador22-Jul-10 7:47
ElGuroProgramador22-Jul-10 7:47 
GeneralRe: Save as Image / BitmapImage Pin
jkristia22-Jul-10 8:38
jkristia22-Jul-10 8:38 
GeneralRe: Save as Image / BitmapImage Pin
Paul Selormey30-Jul-10 14:30
Paul Selormey30-Jul-10 14:30 
AnswerOn the Text Rendering Pin
Paul Selormey18-Jul-10 19:46
Paul Selormey18-Jul-10 19:46 
GeneralRe: On the Text Rendering Pin
jkristia19-Jul-10 3:04
jkristia19-Jul-10 3:04 
GeneralRe: On the Text Rendering Pin
Paul Selormey19-Jul-10 18:51
Paul Selormey19-Jul-10 18:51 
GeneralRe: On the Text Rendering Pin
jkristia20-Jul-10 3:21
jkristia20-Jul-10 3:21 
GeneralMy vote of 5 Pin
Dennis Dykstra14-Jul-10 8:32
Dennis Dykstra14-Jul-10 8:32 
This is very good work and will be an extremely useful addition to WPF's native image capabilities. The lack of support for SVG has been a sore point for me and many others.
Questioncan not compile Pin
Member 278874413-Jul-10 4:07
Member 278874413-Jul-10 4:07 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.