Scalable Vector Graphics and bitmap rendering using Flex

SVG (Scalable Vector Graphics) is one of the most important technologies in the graphics arena. Adobe Flash Player and its variant Flex provide full support for SVG. However, creating complex figures using SVG has always been difficult. Making SVG work with bitmap data requires an understanding of complex concepts like matrix rotation, transparency, and so on. Enter Flex. This article introduces you to the fascinating world of SVG in Flex. Create custom graphics and build appealing flashy components just by vector drawing.

Sandeep Malik (sandeep.malik@in.ibm.com), Tech Lead, IBM

Sandeep Malik photoSandeep Malik is a Tech Lead for IBM Cognos NOW! and works out of India Software Labs, Pune. He has been involved in the design and architecture phase of new generation UI for the Cognos NOW!, and in memory and real-time streaming OBI (Operation Business Intelligence) engine. Sandeep has extensive experience in heavy duty graphics, charting libraries, client-side streaming, non-blocking I/Os, and in general, asynchronous systems. Prior to IBM, Sandeep worked in a network security domain, analyzing the patterns that change the network traffic distribution (for example, botnets, worm scans, and so on). He has also worked on implementing Servlets 2.4 spec in one of his previous companies. During his free time, he enjoys watching cricket and wishes that in his next life he could become a cricketer, too!



17 March 2009

Also available in Chinese Japanese

Introduction

In the world of graphics, two major rendering technologies have dominated the scene. The first and foremost, bitmap rendering, has been around for decades, and technologies and tools revolving around it have greatly matured. Images can be displayed in many formats, namely, jpeg, png, bmp, and so on. Designers, with the help of advanced tools, are capable of generating impressive and sophisticated imagery to be used on Web sites, giving them a fresh look. Tools like Adobe® Photoshop and Image Editor have a long list of advanced algorithms that can be applied to a bitmap of an image and are capable of changing the entire look and feel of it. This has been adopted well, and bitmap images have now become an important part of any Web site design. However, as it stands now, the bitmap rendering suffers from two important drawbacks: First, it is a static image with no motion to it. (Note that we can support animations using the gif format, but most of these animations are predefined and generally do not accommodate user interaction.) Second, they are suited to a particular resolution, or at best a set of resolutions, for which the beauty of an image remains intact. Once the resolution is changed, you start seeing those ugly rectangles (pixel squares), which deteriorate the image quality and take away its luster. Therefore, bitmaps, though capable of generating fantastic images, at best serve a particular domain of interest, where things are static and screen resolutions are fixed.

With the need for growing dynamics in Web content, it is imperative that these images "talk" and "respond" to user interaction. In other words, images need to have a behavioral aspect to them. Scalable Vector Graphics (SVG) do just that. It is important to understand what the words "Scalable Vector Graphics" mean. Vector Graphics means that the images drawn are not a collection of colored pixels. A vector drawing is like a pencil drawing where you take a pencil from one point to another and connect the points with straight lines, curved lines, rectangles, and ellipses. You eventually fill the closed area with various colors. Therefore, a concept of path is fundamental to vector drawings. The benefit is that this path is independent of screen resolution. Generally, the paths are developed on a unit scale, and then the entire graphic is rendered to whatever resolution the user wants, so the image quality remains unchanged even if the resolution is changed to absurd limits. We call vector drawings "scalable" because they can potentially scale to any resolution that is supported by the platform (generally a Web browser).

SVG does come with limitations, though. It is a fairly new technology, and the tools have not matured enough to generate graphics at the same level of detail as a bitmap. Additionally, defining complicated paths for a sophisticated image is not easy. As a result, SVG drawings have mainly been limited to simple circles, rectangles, and the like. Things are improving. New emerging technologies are focused on providing full support for SVG, and tools are getting more advanced.

In this article, I will explain SVG in more detail and show its advantages in comparison to bitmaps. Then I will focus on the current tools and technologies that provide support for SVG, primarily those that are open source. Next, I'll explain how you can use the best of both worlds to create sophisticated, yet "living", graphics using bitmap and SVG together. Finally, I'll provide one such example and walk you through the source code.


An introduction to SVG features

Lately, SVG has picked up momentum. Web site designers have started considering SVG as a robust alternative to bitmaps. Almost all the new RIA (Rich Internet Application)-enabled technologies provide support for vector graphics in some form or the other, and SVG does have some advantages as compared to bitmaps. To start with, SVG is a text-based representation. The entire description of an SVG image is represented by an XML format which has been standardized by W3C. This makes SVG images "human readable" and easily changed with a text editor. Any path in an SVG file can be located by parsing the XML or using advanced techniques like XQuery or XPath. This makes SVG capable enough to respond to user needs.

As an example, suppose that you are making an SVG image of a tiger and you want the tiger's eyes to blink when the user clicks a button. In bitmaps, this would normally be done by embedding two or three images which will overlap with each other to produce the effect. However, in SVG, you can locate the path that draws the shape of the eye of the tiger and then refill this path with a different color, thereby making the appearance that the tiger has closed its eyes! Better still, in an SVG editor, you can draw both the areas (an area is a closed path), the open eye and the closed eye, keeping the latter transparent. To make the tiger blink, you alternate the transparency between the two areas by locating both the areas and paths in the corresponding XML. The end result is an interactive SVG image that changes its behavior based on user interaction.

Many more such interactions are possible by manipulating the paths. In fact, SVG allows you to embed sciplets (ECMAScript), which can include events like mouse-over, mouse-out, click, and so on. The features of SVG make it a serious candidate in graphics technologies, providing two advantages as compared to bitmaps:

  1. You get a scalable image that is independent of screen resolution.
  2. The corresponding size of an SVG image is smaller as compared to that of the bitmap images which are required to achieve the same effect.

The SVG images, being represented as pure text, can be compressed using some of the well-known text compression algorithms like gzip. Such compressed formats are represented as .svgz files, as opposed to .svg files for uncompressed ones.


Open source tools and technologies supporting SVG

Many open source tools and technologies provide excellent support for SVG image designing. Inkscape (see Resources) is one such tool that is worth mentioning. It is free to use and is an excellent platform to create impressive art work. Inkscape allows users to save images not only in SVG format, but in many other formats as well, like XAML (Microsoft® XAML), PS (post script), GPL (GIMP Palette), ODG (OpenDocument Drawing), and so on. You can also export images as bitmap files. Inkscape provides a feature-rich editor to draw sophisticated images with gradients, Beziers, 3D fillers, and so on. It is definitely worth a look for SVG enthusiasts.

Nearly all the latest technologies support vector drawing today, such as Microsoft's Silverlight, Sun®'s JavaFX, OpenLazlo, and Adobe Flex (or Flash). In this article, I will focus more on the support provided by Flex. Flex, an enterprise-oriented variant of Adobe's Flash Player, is a powerful platform for RIA-enabled Web sites. Since Flex inherits most of its features from Flash, it has very good support for vector drawing. Every class in Flex that extends from the base class Sprite, has an embedded graphics object in it. This graphics object can be used to do vector drawing on the sprite. For example, see the code to draw a circle of radius 5:

Listing 1. Example showing the basics of vector drawing
<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="300" 
creationComplete="onCC()">
  <mx:Script>
  <![CDATA[
  private function onCC() : void {
  graphics.clear();
  graphics.lineStyle(2,0xffff00);
  graphics.drawCircle(100,100,5);
  }
  ]]>
 </mx:Script>
</mx:Canvas>

In this case, we have extended from the Canvas (which eventually extends from Sprite), and once the creationComplete event is fired by Canvas, we draw our circle. Note the graphics.clear() call. It is important to clear the previous graphic before a new graphic is drawn. Otherwise, the new drawing will be rendered on top of the older drawing, which will eventually slow down the process because of redrawing over the top of each other. graphics.lineStyle() sets the style of line which is to be used for drawing. Finally, graphics.drawCircle() draws a circle with center (100,100) and radius 5. It is really that simple. Flex supports the union or intersection of shapes as well. Let's say you have two circles, and you want to fill only the non-intersecting sections of these circles. Listing 2 shows how you can do that.

Listing 2. Example showing intersection or union of two vector drawings
<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="300" 
creationComplete="onCC()">
 <mx:Script>
 <![CDATA[ private function onCC() : void {
 graphics.clear();
 graphics.lineStyle(1,0,0);
 graphics.beginFill(0xcccccc);
 graphics.drawCircle(100,100,50);
 graphics.drawCircle(110,100,50);
 graphics.endFill();
 }
 ]]>
 </mx:Script>
</mx:Canvas>

Figure 1 shows what the image looks like when rendered in a browser:

Figure 1. Vector image rendered in a browser
Vector image rendered in a browser

Besides these, the graphics class exposes a lot of other convenient methods that can be used to draw other basic shapes like rectangles, curves, rounded rectangles, lines, triangles, and so on. These should meet the basic requirements of an application developer who wants to use them in a Web site design. However, such basic shapes fall short of expectations when it comes to some heavy duty vector drawing. In such a case, you must make use of some other tools or frameworks that provide advanced support. Degrafa (see Resources) is one such excellent open source framework for creating complex images that are fully interactive as well. The upcoming version of Flex, Flex 4.0, is also going to provide framework-level support for sophisticated SVG drawings. The downside of this is that you have to learn these new APIs to make use of them. However, there is one more way, a sort of middle path, which can help you make good use of bitmaps and vector drawing. I'll explain in the next section.


Using bitmaps and SVG together in Flex

Let's say you want to create a gauge component with three zones in it: Normal, Warning, and Threat. The entire range of zones is from 210 degrees to -30 degrees. This range is divided into three parts. The "threat" zone extends from 210 degrees to 130 degrees. The "warning" zone extends from 130 degrees to 50 degrees, and finally the "normal" zone extends from 50 degrees to -30 degrees. The following figure shows the gauge component.

Figure 2. Gauge component
Gauge component

This is a static image with all the gradients and fills. However, we need to add "life" to it, by adding a needle which shows the current state of some process based on some event. This needle requires an input from the user, and based on that, the gauge component places the needle in the appropriate zone. This kind of interactivity is difficult, if not impossible, to achieve using bitmaps alone. However, using vector drawing, you can achieve it. First, code a needle using vector drawing. Then extend from the base class UIComponent, and override the updateDisplayList() method to draw the custom vector drawing.

Listing 3. Basic design of a needle component
<?xml version="1.0" encoding="utf-8"?>
<mx:UIComponent xmlns:mx="http://www.adobe.com/2006/mxml">
 <mx:Script>
 <![CDATA[
 private var _angle : Number;
 // this angle must range from 210 deg to -30 deg:
 public function set angle(value : Number) : void {
 if(value > 210 || value < -30) throw new Error("Unsupported Angle Value "+value);
 _angle = value;
 inited = true;
 invalidateDisplayList();
 }
 private var inited : Boolean;
 public var center : Point;
 public var radius : Number;
 public function get angle() : Number {
 return _angle;
 }
 ]]>
 </mx:Script>
 </mx:UIComponent>

The needle component declares three variables that it needs before it can display a needle. Those are "angle", "center", and "radius". You also check for the valid angle range when setting the value. Finally, you call invalidateDisplayList() to redraw. Now, take a look at the updateDisplayList() method and see what is happening there:

Listing 4. Main drawing code for the needle component
override protected function 
updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {
 // we need to first convert the angle to a convenient value, 
since flex follows a different angle convention:
 var ang : Number = -angle*Math.PI/180;
 graphics.clear();
 graphics.beginGradientFill(GradientType.RADIAL,[0,0xcccccc],[1,1],
[20,200],null,SpreadMethod.REFLECT);
 graphics.drawCircle(center.x,center.y,30);
 graphics.endFill();
 if(inited) { 
 graphics.lineStyle(10,0,1,false,"normal");
 graphics.lineGradientStyle(GradientType.LINEAR,[0,0xcccccc],[.5,.5],
[20,200],null,SpreadMethod.REFLECT,"rgb",.5);
 graphics.moveTo(center.x,center.y);
 var p : Point = getCoordinates(ang);
 graphics.lineTo(center.x + p.x,center.y + p.y);
 graphics.lineStyle(1,0,0);
 graphics.moveTo(center.x,center.y);
 }

For an angle of 30 degrees, the needle component looks like Figure 3.

Figure 3. Needle component at 30 degrees
Needle component at 30 degrees

All that is needed now is to superimpose the bitmap and this vector drawing, and you should have a gauge component ready. See the following code snippet:

Listing 5. Gauge component
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" 
layout="absolute" xmlns:components="article2.components.*" backgroundColor="0xffffff">
 <mx:FormItem label="Change the angle" x="20" y="10">
 <mx:HSlider id="slider" minimum="-30" maximum="210" value="0" 
liveDragging="true" change="needle.angle = slider.value"/>
 </mx:FormItem>
 <mx:Canvas y="50" backgroundImage="article2/images/gauge_skin.PNG" 
width="362" height="310" id="gauge"/>
 <components:Needle id="needle" center="
{new Point(gauge.x+gauge.width/2,gauge.y+gauge.height/2)}" radius="100"/>
 </mx:Application>

Figure 4 shows a snapshot of the above code in action.

Figure 4. Gauge component in action
Gauge component in action

And that's it; the working gauge component is ready! You can download the working swf file below.


Summary

This article gave a brief description of SVG and bitmaps. You saw how SVG can help bring user interaction to static bitmaps. Embedding a rich bitmap is fairly easy in Flex (by providing the backgroundImage property), and adding a component with vector drawing is even easier. This example opens up a new door of opportunities where an application designer or developer can make the best use of both worlds, while sticking to traditional bitmap drawing and using Flex to add SVG support.


Download

DescriptionNameSize
.swf file created in this articleDownload.zip279KB

Resources

Learn

Get products and technologies

  • Learn about and download Inkscape for a variety of platforms.
  • Get more information about the Degrafa framework.
  • IBM trial products for download: Build your next development project with IBM trial software, available for download directly from developerWorks.

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into Web development on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Web development
ArticleID=376302
ArticleTitle=Scalable Vector Graphics and bitmap rendering using Flex
publish-date=03172009