Scalable Vector Graphics* (SVG) is a family of specifications of an XML-based file format for two-dimensional vector graphics, both static and dynamic (that is, interactive or animated), text or embedded raster graphics. The SVG specification is a royalty-free vendor-neutral open standard that has been under development by the World Wide Web Consortium* (W3C) since 1999.
SVG images and their behaviors are defined in XML text files. This means that they can be searched, indexed, scripted and, if required, compressed. As XML files, SVG images can be created and edited with any text editor.
SVG files are compact and provide high-quality graphics on the Web, in print, and on resource-limited handheld devices. In addition, SVG supports scripting and animation, so is ideal for interactive, data-driven, personalized graphics.
Using SVG has many benefits. First, you don’t need to have pictures in different resolutions, no need to scale. Second, SVG is an XML file, so its size is much smaller than the raster size format for the same image. This also helps to change the picture on the fly.
SVG allows three types of graphic objects: vector graphics, raster graphics, and text. Graphical objects, including PNG and JPEG raster images, can be grouped, styled, transformed, and composited into previously rendered objects.
Native Android* applications do not support SVG XML files. But SVG XML files could be parsed in browsers starting with Android 3.0 (see Figure 1). This chapter integrates the SVG-Android open source library into codebase and provides an example application on Intel® architecture Android Ice Cream Sandwich (ICS).
1. SVG Functionality
The SVG 1.1 specification defines 14 functional areas of feature sets, which are:
- Paths
- Basic shapes
- Text
- Painting
- Color
- Gradients and patterns
- Clipping, masking, and compositing
- Filter effects
- Interactivity
- Linking
- Scripting
- Animation
- Font
- Metadata
2. SVG Shapes
SVG's predefined shape elements are:
- Rectangle <rect>
<svg> <rect x="50" y="20" width="150" height="150" style="fill: red; stroke: yellow; stroke-width: 5; opacity: 0.5" /> </svg>
- Circle <circle>
<svg > <circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red" /> </svg>
- Ellipse <ellipse>
- Line <line>
- Polyline <polyline>
- Polygon <polygon>
- Path<path>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"> <path d="M150 0 L75 200 L225 200 Z" /> </svg>
Figure 1: SVG Implementation on Android Device
Source: Intel Corporation, 2012
3. SVG Library Integration
Create a file named svgandroid.xml to describe svgandroid.jar. Place svgandroid.jar in /system/framework folder and svgandroid.xml in the /etc/permissions folder. Applications will discover svgandroid.jar library through svgandroid.xml.
Put the following code into the svgandroid.xml:
<?xml version="1.0" encoding="utf-8"> <permissions> <libraryname="svgandroid" file="/system/framework/svgandroid.jar"/> </permissions>
Use the <use-library> declaration in the AndroidManifest.xml file. This method loads the svgandroid packages. They will not be loaded automatically.
<uses-library android:name="svgandroid" android:required="true" />
Set android:required="true". The Android system would not permit an application on a device without this library.
If this application is installed on Android devices without this library, the following error message occurs:
Failure [INSTALL_FAILED_MISSING_SHARED_LIBRARY]
This element also affects the availability of the application on Market. The Android device could not list this application on Market without the library.
4. Render a File Using Revised SVG
This section shows how to render a file using revised SVG.
4.1. What is SAX?
SAX (Simple API for XML) is an event-based sequential access parser API generated by the XML-DEV mailing list for XML documents. SAX’s mechanism for reading data from an XML document is very different than the one provided by the Document Object Model (DOM). Where the DOM operates on the document as a whole, SAX parsers operate on each piece of the XML document sequentially.
4.2. Benefits
SAX parsers have certain benefits over DOM-style parsers. A SAX parser typically uses much less memory than a DOM parser. DOM parsers must have the entire tree in memory before any processing can begin, so the amount of memory used by a DOM parser depends entirely on the size of the input data. The memory footprint of a SAX parser, by contrast, is based only on the maximum depth of the XML file (the maximum depth of the XML tree) and the maximum data stored in XML attributes on a single XML element. Both of these are always smaller than the size of the parsed tree itself.
Because of the event-driven nature of SAX, processing documents can often be faster than DOM-style parsers. Memory allocation takes time, so the larger memory footprint of the DOM is also a performance issue.
Due to the nature of DOM, streamed reading from disk is impossible. Processing XML documents larger than main memory is also impossible with DOM parsers, but can be done with SAX parsers. However, DOM parsers can make use of disk space as memory to sidestep this limitation.
4.3. Drawbacks
The event-driven model of SAX is useful for XML parsing, but it does have certain drawbacks.
Certain kinds of XML validation require access to the document in full. For example, a DTD IDREF attribute requires that there be an element in the document that uses the given string as a DTD ID attribute. To validate this in a SAX parser, one would need to keep track of every previously encountered ID and IDREF attributes to see if any matches are made. Furthermore, if an IDREF does not match an ID, the user only discovers this after the document has been parsed. If this linkage was important to building functioning output, then time has been wasted in processing the entire document only to throw it away.
Additionally, some kinds of XML processing simply require having access to the entire document. XSLT and XPath, for example, need to be able to access any node at any time in the parsed XML tree. While a SAX parser could be used to construct such a tree, the DOM already does so by design.
4.4. How to Implement the SAX Parser in Android
When implementing SAX parser, the class needs to inherit “DefaultHandler". And there are a few methods that need to be overridden when inheriting the “DefaultHandler"—default base class for SAX2 event handlers in Android. These methods include startElement, endElement, startDocument, and endDocument. You can easily see what each function does by its name. For example, startDocument means when the SAX starts to parse the document, it will trigger the event and call the startDocument method. Once the SAX parses any tag of XML file, it will call startElement, so you can get the tag name, attribute, and some other information relevant to the tag. The other methods, endDocument, startElement, and endElement, are self-explanatory.
4.5. Why Revise the Original SVG Library?
Since the original library can’t render the SVG file with attributes in the group tag (<g>), we must add a register to store the style attribute with a <g> tag. If there is already a style attribute in the inner render element, the style attribute will replace the one in the <g> tag.
We recommend using SAX to parse the SVG file. When we parsing the <g> tag, we retrieve the entire attribute into the instance –g_prop, which is an internal class of the properties.
public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException { …… } else if (localName.equals("g")) { …… pushTransform(atts); g_prop = new Properties(atts); } …… } public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException { …… } else if (localName.equals("g")) { …… pushTransform(atts); g_prop = new Properties(atts); } …… }
When we parse the <rectangle>, <path> or any other rendering tags, we need to check if there is any style associated with the tag. If there is, we need to get the attributes. The methods doFill, doStroke help to initiate the style of fill and stroke of the canvas. After these methods are invoked, we can draw the parsed element onto the canvas.
Properties props = new Properties(atts); if (doFill(props, gradientMap)) { doLimits(p); canvas.drawPath(p, paint); } else { if(g_prop != null) { if(doFill(g_prop, gradientMap)) { doLimits(p); canvas.drawPath(p, paint); } } } if (doStroke(props)) canvas.drawPath(p, paint); else { if(g_prop != null) { if(doStroke(g_prop)) canvas.drawPath(p, paint); } } popTransform(); } Properties props = new Properties(atts); if (doFill(props, gradientMap)) { doLimits(p); canvas.drawPath(p, paint); } else { if(g_prop != null) { if(doFill(g_prop, gradientMap)) { doLimits(p); canvas.drawPath(p, paint); } } } if (doStroke(props)) canvas.drawPath(p, paint); else { if(g_prop != null) { if(doStroke(g_prop)) canvas.drawPath(p, paint); } } popTransform(); }
3.6. SVG XML File with Attributes in the Rendering Tag
The following is an SVG XML file with attributes in the rendering tag (see Figure 2).
<path display="none" fill="#FFFFFF"
d="M268.461,471.01c2.526,0,4.575,2.048,4.575,4.571c0,2.529-2.049,4.576-4.575,4.576
c-2.525,0-4.574-2.047-4.574-4.576C263.887,473.058,265.936,471.01,268.461,471.01z"/>
Figure 2: SVG Implementation on Android Device
Source:. Intel Corporation, 2012
4. SVG XML File with Attributes in Group Tag
The following is an SVG XML file with attributes in the group tag.
<g style="fill: #ffffff; stroke:#000000; stroke-width:0.172">
<path d="M-122.304 84.285C-122.304 84.285 -122.203 86.179 -123.027 86.16C-123.851 86.141 -140.305 38.066 -160.833 40.309C-160.833 40.309 -143.05 32.956 -122.304 84.285z"/>
</g>