Click here to Skip to main content
Click here to Skip to main content

SVGImage Control

, 29 Jul 2010
Rate this:
Please Sign up or sign in to vote.
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.

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.

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)

About the Author

jkristia
Software Developer (Senior)
United States United States
No Biography provided

Comments and Discussions

 
QuestionFork at Github... Pinmemberjogibear998813-Dec-12 23:58 
SuggestionSome minor changes Pinmemberwenzor19-Jan-12 7:16 
QuestionHow about separating SVG Library from Clipart Viewer? PinmemberLastZolex6-Jan-11 21:30 
GeneralBug PinmemberTomice27-Oct-10 10:29 
GeneralRe: Bug Pinmemberjkristia28-Oct-10 3:11 
QuestionCan I use SVGImage on WinForm? PinmemberVikram Lele23-Sep-10 1:27 
AnswerRe: Can I use SVGImage on WinForm? Pinmemberjkristia23-Sep-10 3:08 
GeneralRe: Can I use SVGImage on WinForm? PinmemberVikram Lele23-Sep-10 18:09 
GeneralNice! Pinmemberreflex@codeproject29-Jul-10 10:34 
GeneralSave as Image / BitmapImage PinmemberElGuroProgramador22-Jul-10 7:47 
GeneralRe: Save as Image / BitmapImage Pinmemberjkristia22-Jul-10 8:38 
GeneralRe: Save as Image / BitmapImage PinmemberPaul Selormey30-Jul-10 14:30 
AnswerOn the Text Rendering PinmemberPaul Selormey18-Jul-10 19:46 
GeneralRe: On the Text Rendering Pinmemberjkristia19-Jul-10 3:04 
GeneralRe: On the Text Rendering PinmemberPaul Selormey19-Jul-10 18:51 
GeneralRe: On the Text Rendering Pinmemberjkristia20-Jul-10 3:21 
GeneralMy vote of 5 PinmemberDennis Dykstra14-Jul-10 8:32 
Questioncan not compile PinmemberMember 278874413-Jul-10 4:07 
AnswerRe: can not compile Pinmemberjkristia13-Jul-10 4:23 
QuestionAny plan for a SVG Editor? PinmemberJohnWindy11-Jul-10 22:43 
AnswerRe: Any plan for a SVG Editor? [modified] Pinmemberjkristia12-Jul-10 3:06 
AnswerRe: Any plan for a SVG Editor? PinmemberBill Seddon13-Jul-10 0:42 
GeneralRe: Any plan for a SVG Editor? Pinmemberjkristia13-Jul-10 3:05 
GeneralRe: Any plan for a SVG Editor? PinmemberJohnWindy13-Jul-10 22:05 
QuestionLink image is missing? PinmemberJohnWindy9-Jul-10 2:37 
AnswerRe: Link image is missing? [modified] Pinmemberjkristia9-Jul-10 3:31 
GeneralRe: Link image is missing? PinmemberJohnWindy11-Jul-10 22:27 
GeneralMy vote of 5 Pinmembergeo_m8-Jul-10 1:20 
GeneralBug Pinmemberreflex@codeproject7-Jul-10 8:40 
GeneralRe: Bug Pinmemberjkristia7-Jul-10 9:52 
GeneralRe: Bug Pinmemberreflex@codeproject7-Jul-10 11:24 
GeneralRe: Bug Pinmemberjkristia7-Jul-10 15:24 

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

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

| Advertise | Privacy | Mobile
Web01 | 2.8.140721.1 | Last Updated 29 Jul 2010
Article Copyright 2010 by jkristia
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid