Cosc 5/4730 SVG and Scalable 2D Vector Graphics API (JSR 226) What is Scalable Vector Graphics? • Scalable Vector Graphics (SVG) is an XML grammar for rich, dynamic 2D graphics. It offers a wide array of applications and advantages beyond those of other 2D formats, such as PDF or PostScript. • SVG graphics can be scripted, which means that a graphic and its features can be modified in response to user interface events. For example, you can change the color of a circle when the mouse cursor moves over that circle. SVG can also handle hyperlinking and declarative animation. • JSR 226 is the svg implementation for JavaME – JavaDoc's http://tlbs.us/dev/api/jsr-226/ • SVG 1.1 xml reference (lists most attributes) – http://www.zvon.org/xxl/svgReference/Output/index.html Example <?xml version="1.0" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd"> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="300" height="200" viewBox="0 0 300 200"> <rect x="90" y="50" rx="30" ry="30" width="120" height="100" fill="#FEB32B" stroke="#FF6600" stroke-width="10" /> </svg> Example (2) • The actual SVG content starts with the <svg> element tag. – The tag defines the namespaces it uses and then specifies three attributes width, height and viewBox, which define the viewable area of the SVG file. • This SVG file defines only one graphical element, which is a rectangle. – The rectangle is specified simply by a <rect> element tag. – The element tag contains various attributes that define the properties of the rectangle, such as its location (x, y), the radius for its rounded corners(rx, ry), its dimensions (width, height), the color to fill the rectangle with (fill), the color for the rectangle border (stroke) and the width of the border (strokewidth). Colors • Colors can be specified in several ways – – – – Three digit hex — #rgb #fff (white) 4096 colors Six digit hex — #rrggbb 16777216 colors integer function rgb(rrr,ggg,bbb) Float functional rgb(R%, G%, B%) rgb (12%, 34%, 29%) – color keyword: • Note must be lower case Shapes • SVG graphics can contain basic shapes: rectangles, circles, ellipses, lines, polygons, and polyline • Rectangles you saw in the example • Example over the couple of slides. circle and ellipse <circle cx="138.0" cy="245" r="60" fill="aqua" stroke="blue" stroke-width="2" /> <ellipse cx="141" cy="249" rx="60" ry="40" fill="silver" stroke="black" stroke-width="10" /> Line and ployline <line x1="50" y1="150" x2="250" y2="50" stroke="blue" stroke-width="10" /> <polyline points="50,50 50,150 100,150, 100,50, 150,50 150,150 200,150 200,50 250,50 250,150" stroke="black" fill="white" stroke-width="10" /> • with fill="green" Polygon • specify a set of points <polygon points="150,50 250,150 50,150" fill="olive" stroke="green" stroke-width="3" /> path shape • This is a very simple example, but path elements can describe arbitrarily complex shapes. <path d="M50,50 l200,0 c0,100 0,100 -100,100 Z" width="120" height="100" fill="red" stroke="black" stroke-width="5" /> text • You can include simple or very sophisticated text in SVG documents. <text font-size="8" font-family="sans-serif" font-weight="bold" fill="black" transform="translate(15,0) scale(1)" y="-10 0 10 20 30 30 30 40 50 60 70 80 90 100 110 100 90 80"> SVG has fancy text</text> <text font-size="8" font-family="sans-serif" font-weight="bold" fill="red" transform="scale(2) rotate(45)" x="75" y="0"> Isn't this cool! </text> Painters model • objects are draw in order listed. <rect x="90" y="50" width="120" height="100" fill="aqua" stroke="blue" stroke-width="2" /> <circle cx="150" cy="100" r="60" fill="red" stroke="maroon" stroke-width="2" /> Grouping. • • • • <g id=“name”> … </g> Allows you to group elements together to create something more interesting • More interesting – animate <g id="runner" > <ellipse id=“head" fill="none" stroke="#ff0000" stroke-width="1" cx="1" cy="-38" rx="11" ry="9.5"/> <polyline id="line1“ fill="none" stroke="#ff0000“ stroke-width="1" points="1,29 1,7 "/> … </g> Creating the SVG file • Either create the svg file on your own • Use one of the many applications out there. – example: Illustrator, CorelDraw • Open Source app – inkscape: http://www.inkscape.org/ Once you have the xml file. • Use the packages javax.microedition.m2g.* and org.w3c.dom.* and org.w3c.dom.svg* • You can load, display, and manipulate the xml. – including adding more xml. package org.w3c.dom • Accessing the xml • interfaces – document • interface that represents the whole xml document – element • mostly overriding by using org.w3c.dom.svg – node • mostly overriding by using org.w3c.dom.svg package org.w3c.dom.svg • SVT Tiny 1.1 DOM API defined in this specification is subset of W3C SVG Tiny 1.2 uDOM. – SVGAnimationElement This interface represents an Animation element, which contains methods to control the timing of animations. – SVGElement This interface represents an SVG element in the document tree. – SVGLocatableElement This interface represents an SVGLocatableElement. – SVGMatrix This interface represents an "SVGMatrix" datatype, identified by an affine transform. – SVGPath This interface represents an "SVGPath" datatype used to define the path geometry. – SVGPoint This interface represents an "SVGPoint" datatype, identifiend by its x and y components. – SVGRect This interface represents an "SVGRect" datatype, consisting of a minimum X, minimum Y, width and height values. – SVGRGBColor This interface represents an "SVGRGBColor" datatype made up of red, green, and blue components. – SVGSVGElement This interface represents <svg> element in (SVG) document tree. javax.microedition.m2g • ScalableGraphics This is the fundamental class for 2D rendering. • ScalableImage This class models images in vector format, such as the Scalable Vector Graphics (SVG) image format. • SVGAnimator The SVGAnimator class handles automatic rendering of updates and animations in an SVGImage to a target user interface (UI) component. • SVGImage This class represents an SVG image conforming to the W3C SVG Tiny 1.1 Profile. – subclassed of ScalableImage Displaying SVG image • First load the svg file into an SVGImage – Open our input stream of the svg file we want to load. InputStream inputStream = getClass().getResourceAsStream(url); – Load our svg image from the input stream. svgimage (SVGImage) SVGImage.createImage( inputStream, null); • Now we need to get into a Field, so we can add to the screen. Displaying SVG image • Get the ui field from the animator. String FIELD_PACKAGE = "net.rim.device.api.ui.Field"; svganimator = SVGAnimator.createAnimator( svgimage, FIELD_PACKAGE); • Create an interactive svg animator which hosts our ui field. svgfield = (net.rim.device.api.ui.Field) svganimator.getTargetComponent(); • Add the field to the screen. add (svgfield); svg Example • Assuming this is the svg file <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11tiny.dtd"> <svg width="300" height="200" viewBox="0 0 300 200" preserveAspectRatio="xMidYMid meet" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" baseProfile="tiny"> <rect id="Rect" x="90" y="50" width="120" height="100" fill="aqua" stroke="blue" stroke-width="2" /> <circle id="0Circle" cx="150" cy="100" r="60" fill="red" stroke="maroon" fill-opacity = "1.0" stroke-width="2" /> </svg> Changing the xml • You can change an attribute (trait) of an element. First we need to get that element in an SVGElement and then change it. – The simplest way is to get the element by ID tag. – For the circle it's id is 0circle SVGElement e = (SVGElement) svgImage.getDocument().getElementById( "0Circle"); • Get the getDocument() returns the entire document, but we only need one element, by ID, which is put into an SVGElement. Changing the xml (2) • SVGElement provides a number of "get" and "set" methods to change the xml • Example, we want to add 1 to the radius of the circle float x = e.getFloatTrait("r"); • "r" is the attribute for radius of the circle. String str = e.getTrait("r"); • We can also get the info as a string, but not useful in this case. Changing the xml (3) • set work simliar – setTrait("trait", String) or – setFloatTrait("trait", float); • To change the radius of our 0circle by one e.setFloatTrait("r", 1.0+e.getFloatTrait("r")); The next repaint() would then redraw with the new size. Adding new objects. • with the same svgImage we loaded, we can add new objects. • This time we need the svg part of the xml document, so we can add a new element to it. SVGSVGElement root = (SVGSVGElement) svgImage.getDocument().getDocumentElement(); • If we want to add the olive triangle, we need to create the element SVGElement tri = (SVGElement) (svgImage.getDocument().createElementNS( "http://www.w3.org/2000/svg", "polygon" )); Adding new objects (2) • get the olive color to use SVGRGBColor olive = root.createSVGRGBColor( 128, 128, 0 ); • And set all the traits tri.setRGBColorTrait( "fill", olive ); tri.setTrait( "points", "150,50 250,150 50,150" ); tri.setTrait("id","triangle"); • to appended to the end (now drawn on top) root.appendChild(tri ); Adding new objects (3) • To insert it at the beginning or in the middle, we need a reference to the element we are inserting it before. – Let's insert at the first element, ie before Rect element. root.insertBefore(tri, svgImage.getDocument().getElementById("Rect") ); Removing elements. • removechild(SVGElement); – But only if the Element does not have an ID. – Otherwise Elements with an ID tag, can not be removed. • Also, ID tags can not be modified – or removed. SVGAnimator • So far we have a static image. • the SVGAnimator updates the field when the SVGImage is modified and animation updates happen periodically as well. – Deals with animate attributes automatically. animate • There are 4 animate xml that can be used – animate, generalized, can do most everyting. – animateMotion, for movement – animateColor, for changing the colors – animateTransform, which is used to move a "whole" object around the viewport. animate example 1 • Change the cx trait <circle id="0Circle" cx="150" cy="100" r="60" fill="red" stroke="maroon" stroke-width="2" > <animate attributeName="cx" from="150" to="175" dur="5s" repeatCount="indefinite"/> </circle> animate example 2 • Changing the color <rect id="0Rect" x="90" y="50" width="120" height="100" fill="aqua" stroke="blue" fill-opacity = "1.0" stroke-width="2"> <animateColor attributeName="fill" values="red;green;blue;aqua" dur="5s" repeatCount="indefinite" /> </rect> animate example 3 • More then one animate can be used together <rect id="0Rect" x="90" y="50" width="120" height="100" fill="aqua" stroke="blue" fill-opacity = "1.0" stroke-width="2"> <animateColor attributeName="fill" values="red;green;blue;aqua" dur="5s" repeatCount="indefinite" /> <animate attributeName="y" from="50" to="75" dur="10s" repeatCount="indefinite"/> </rect> animation • We just need to “start” the animator. svganimator.play(); • Since the last examples use indefinite, We may want to stop it svganimator.stop(); Interaction • Using the standard listeners for touch or keys – We can change/interact with the animation. keyListener public boolean keyChar(char if (key == 'u' ) { scale (0.10f); return true; } else if (key == 'd') scale (-0.1f); return true; } else if (key == 'l') rotate(-10.0f); return true; } else if (key == 'r') rotate(10.0f); return true; } return false; } key, int status, int time) { { { { keyListener (2) private void rotate( final float delta ) { // put ourselves on the animator's thread animator.invokeLater( new Runnable(){ public void run(){ // execute the transformation Document document = svgImage.getDocument(); SVGSVGElement root =(SVGSVGElement) document.getDocumentElement(); root.setCurrentRotate( root.getCurrentRotate() + delta ); } } ); } private void scale( final float delta ) { // put ourselves on the animator's thread animator.invokeLater( new Runnable(){ public void run(){ // execute the transformation Document document = svgImage.getDocument(); SVGSVGElement root = (SVGSVGElement) document.getDocumentElement(); root.setCurrentScale( root.getCurrentScale() + delta ); } } ); } Groups in SVG • When we look at the <g> tag for grouping the animation changes – We still need to play(), but also need to activate a group as well. • It maybe the way the xml is laid out, I’m not sure. • Svgimage.activate(); //now the runner will animate. Examples • svg.zip – Uses the runner.svg file, press play to have it animate • svg2.zip – Uses the example through this lecture. – plays runs the animation • u and d scale and l and r rotate the image. • Blackberry svganimator example is very good place to see more svg animation as well. References • • The Runner svg image is from Blackberry’s svganimatordemo. Javadoc's – – http://tlbs.us/dev/api/jsr-226/ http://theoreticlabs.com/dev/api/jsr-226/ • – • • • • • • • • These two are the same, but hopefully one still responds http://www.zvon.org/xxl/svgReference/Output/index.html For xml documentation for tinySVG 1.1 http://www.w3.org/TR/2008/REC-SVGTiny12-20081222/painting.html#Color http://developers.sun.com/mobility/midp/articles/s2dvg/index.html http://www.forum.nokia.com/document/Java_Developers_Library_v2/?content=GUID-57CBAA71C915-4CB4-9AF5-1E9BF4C613F2.html http://developers.sun.com/events/techdays/presentations/2007/TD_BOS_JavaME_Patel.pdf https://meapplicationdevelopers.dev.java.net/uiLabs/RenderSVGImage.html https://meapplicationdevelopers.dev.java.net/uiLabs/IntroTo226.html https://meapplicationdevelopers.dev.java.net/uiLabs/IntroToSVG.html Creating svg from scatch. (no svg file needed) http://today.java.net/pub/a/today/2007/07/10/scalable-vector-graphics-on-java-me.html Q&A