Monday, February 18, 2008

SOT: SVG made easy with Inkscape

So I just discovered the wonders that are possible with SVG, thanks to an older entry on Barney Boisvert's blog. (Hey, better late than never ;) While the effects you can achieve are impressive, the SVG syntax is a bit daunting. I thought to myself there is no way people code this stuff by hand. Okay, maybe a few mutant programmers that write code in their sleep, are fluent in machine language, think notepad is the ultimate editor and that IDE's are for sissies. Needless to say I am not one of them, so off to google I went.

A quick search turned up a program called Inkscape. It has been around for a few years, so veterans may already be aware of it. But I just downloaded it this weekend and am very impressed with it. It is a graphical editor, like Illustrator, that makes handling SVG a breeze. The current stable release is 0.45.1, but the bleeding edge version 0.46 has a bunch of cool new features in it. So it is worth a look.

Now I freely confess I am "artistically challenged". But using only Inkscape and this Photoshop tutorial, I was able to create this cool aqua sphere in very little time. Admittedly an old look, but I like it.

It was a lot easier than I thought. Towards the end I even got bold and decided to play around with some of the effects ;) So lest you think I cannot follow instruction, that is why my image does not look exactly like the original ;)



You can also draw text on a path, will very little effort. Just draw a path, or a shape like a circle. Then draw some text. Select both the text and the path shape. Then select Text > Put On Path from the top menu. That is it. Save the result as an Plain .SVG file and you can modify it to work with dynamic text.




Two examples are drawing text on a circle or a spiral. While these examples are rather bland, you can see a more interesting use of text on a spiral on Jon Aquino's blog.



If you have not used Inkscape before, it is a great application. Definitely worth checking out!

ColdFusion Code (Based on code by Barney Boisvert)

See also Installing Batik 1.7 for instructions.


<!--- read in the file containing the svg text --->
<cffile action="read" file="#ExpandPath('spiralText.svg')#" variable="svgXML">

<!--- fill in the dynamic values --->
<cfset dynamicText = "Round and round we go. Where we stop, nobody knows. Round and round we go. ">
<cfset dynamicText = dynamicText & "Stop the ride. I am dizzy and want to get off. Round and round we go..">
<cfset svgXML = replaceNoCase(svgXML, "{fontSize}", "18px", "all")>
<cfset svgXML = replaceNoCase(svgXML, "{fontWeight}", "bold", "all")>
<cfset svgXML = replaceNoCase(svgXML, "{fontFamily}", "Arial", "all")>
<cfset svgXML = replaceNoCase(svgXML, "{displayText}", dynamicText, "all")>

<!--- get my javaloader instance from the server scope --->
<cfset javaLoader = server[MyUniqueKeyForJavaLoader]>

<!--- Based on code by Barney Boisvert --->
<!--- create an image from the svg text. save it to a file and display it --->
<cfset transcoder = javaLoader.create("org.apache.batik.transcoder.image.PNGTranscoder").init()>
<cfset inputStream = createObject("java", "java.io.StringBufferInputStream").init(svgXML)>
<cfset input = javaLoader.create("org.apache.batik.transcoder.TranscoderInput").init(inputStream)>
<cfset outputStream = createObject("java", "java.io.FileOutputStream").init(ExpandPath("spiralText.png"))>
<cfset output = javaLoader.create("org.apache.batik.transcoder.TranscoderOutput").init(outputStream)>
<cfset transcoder.transcode(input, output)>
<cfset outputStream.close()>
<img src="spiralText.png">


SpiralText.svg

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.0"
width="744.09448"
height="1052.3622"
id="svg2220">
<defs
id="defs2222" />
<g
id="layer3">
<path
d="M 191.62299,620.98969 C 203.24843,638.55675 195.73477,662.11559 178.69969,673.05495 C 156.04225,687.60481 125.98484,677.85885 112.21349,655.85044 C 94.285527,627.19923 106.67232,589.52943 134.54618,572.47742 C 170.16978,550.68446 216.65637,566.15584 237.47088,600.86248 C 263.64902,644.51256 244.61396,701.11114 202.03179,726.20328 C 149.22546,757.32016 81.128622,734.20688 51.210357,682.6308 C 14.567727,619.46258 42.30929,538.38991 104.07353,503.06359 C 178.88529,460.27469 274.50291,493.23021 315.85271,566.45287 C 365.44201,654.26609 326.65114,766.08946 240.6236,814.11178 C 184.43295,845.47855 115.25976,847.23777 56.70371,821.19779"
transform="matrix(-6.4631751e-2,-0.9979092,0.9979092,-6.4631751e-2,-287.68055,656.94182)"
style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:none;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
id="path2368" />
<text
transform="translate(-145.46196,-236.3757)"
style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
id="text2377"
xml:space="preserve"><textPath
xlink:href="#path2368"
id="textPath2381"><tspan
style="font-size:{fontSize};font-style:normal;font-variant:normal;font-weight:{fontWeight};font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:{fontFamily}"
id="tspan2379">{displayText}</tspan></textPath></text>
</g>
</svg>

6 comments:

PaulH February 19, 2008 at 12:18 AM  

you might be interested in postGIS which has a function to render it's spatial data as SVG (though frankly serious spatial data is usually too big to display using SVG).

stelt February 19, 2008 at 7:00 AM  

Lots more SVG on http://svg.startpagina.nl (the SVG link resource)

Barney February 19, 2008 at 2:08 PM  

You might also consider CFINCLUDEing your SVG template so you can use full CFML markup inside, rather than just the token replacement you're currently doing.

cfSearching February 19, 2008 at 2:57 PM  

@barney,

Yes. I was considering putting the code in a more generic function. So that is why I went with replace over cfinclude. But that is good idea too.

@paulH,

It does look interesting. Thanks. I will check it out.

@stelt,

Cool. Now that is a lot of links! ;)

cfSearching February 19, 2008 at 3:00 PM  

@barney,

Btw, thanks for the great article too. I had never even used SVG or Batik before I read it. This is very cool stuff!

cfSearching March 21, 2008 at 7:22 AM  

@paulH,

I finally got around to checking out postGIS. I hate to sound like a teenager, but .. WOW .. that is some seriously cool stuff ;)

  © Blogger templates The Professional Template by Ourblogtemplates.com 2008

Header image adapted from atomicjeep