Mesh Gradients in SVG

I’ve been working on adding Mesh Gradients to the SVG standard and in principle they have been accepted as part of SVG 2. In particular, the SVG working group has approved the addition of Coons Patch mesh gradients. This type of mesh is powerful enough to handle the requirements for most advanced gradients use cases and at the same time is a convenient form for use in content creation. Coons Patch meshes are included in the PostScript and PDF standards (Type 6 Shading) and the Cairo rendering library supports them in trunk. I’ve added support for meshes to a my own branch of Inkscape for testing purposes. The SVG working group has identified one problem with the meshes: It is not always possible to have smooth color transitions across mesh boundaries. To understand why this can be a problem, one must understand how the meshes work. A Coons Patch mesh is composed of an array of Coons Patches. A Coons Patch consists of four Bézier curves along the sides with colors defined at each corner. The color of any point inside the patch is determined by a two-dimension bi-linear interpolation of the corner colors followed by a geometric mapping defined by the Bézier patch sides.
Left: square showing color interpolation. Right: patch showing result of mapping.

Left: Color defined by a two-dimension bi-linear interpolation of the corner colors. Right: the color interpolation mapped to the patch region. The Bézier end points (corners) and handles are shown as diamonds and circles respectively.

The key word in the above description is “linear”. Working in one dimension, linear interpolation between two colors works exactly the same as in the linear gradient of SVG 1. A patch corresponds to the interval between two color “stops”. The linear gradient in the following figure consists of three stops or two “patches”. The color transition between the two patches is continuous but not smooth.
Top: a three stop linear gradient. Bottom: the RGB color profile of the gradient.

Top: A three stop gradient with stop colors blue, purple, and yellow. Bottom: Plots of the red, green, and blue profiles of the gradient.

Lack of smoothness in some cases can lead to visual artifacts as illustrated in the following figure:
Six linear gradients with the second and fourth stops in different places.

Linear gradients consisting of five stops. The outer two are black, the center one is white, and the remaining two are set to 90% white. The position of the 90% white stops are different for each gradient. The red line shows the black to white profile for each gradient.

As one can see in the above linear gradients, the eye is fooled into thinking that the location of the 90% white stop is whiter than the areas immediate right and left of the stop. This is due to the Mach Banding effect. With meshes, one can move the Bézier “handles” to alter the color profile. This is equivalent to stretching or shrinking a section of the patch. If the side is linear, moving the handles will not change the shape of the patch but will change the “speed” of the curve’s parameterization. The following figure shows how moving the handles can yield a smooth transition and eliminate the Mach Banding:
Three gradients illustrating how to smooth a color transition.

The top gradient is a linear gradient. The middle gradient is a Coons Patch mesh gradient that duplicates the linear gradient. The location of the Bézier handles (circles) are shown in blue. They are at their default positions spaces one-third of the way between the corner points (squares), corresponding to a linear interpolation. The bottom gradient is a Coons Patch mesh gradient where the top and bottom handles have been moved to smooth out the transition across the patch boundaries. The 90% stop has been changed to 80%. The purple line on the bottom gradient shows the new color profile.

As illustrated above, it is possible in some cases to obtain smooth transitions with Coons Patch mesh gradients across patch boundaries. However there are cases where it is not possible. Consider the center “stop” in the above figure. No matter how you manipulate the handles you can not achieve a smooth transition at this point. The derivative of the color profile cannot be made to be zero. The following figure shows some of the profiles available for one patch:
Three gradients showing the range of allowed color profiles when moving Bézier handles.

Three Coons patch meshes are shown where the left corners are black and the right corners are white. Overlaid each gradient is the color profile determined by the handle placements of the top and bottom Bézier curves. The top gradient shows the color profile with the default handle placement (i.e. when a curve is defined by a “lineto”). The Bézier handles of top and bottom of the mesh are shown in blue while the color profile with the profile’s effective Bézier handles are shown in red. The middle gradient shows the the color profile when the handle “lengths” are zero (i.e. when the handles are placed on top of the corners. The bottom gradient shows the color profile when the handles are placed over the opposite corners.

Note that in the above figure the handles of the effective Bézier curve color profile are constrained to horizontal lines one-third of the distance between the top and bottom range of the color profile. As a result, one can never have a profile where the derivative of the color change at a boundary is zero. Also note, that while the handles can be moved outside the patch region to the left or right, a discontinuity in the color profile will result as the effective profile Bézier will overlap itself. Another case where it is impossible to obtain a smooth transition is when the different primary colors (red, green, blue) have different profiles. In general, only the profile of one color can be made smooth. So how do Adobe Illustator and Corel Draw get smooth transitions? I don’t have either one so I can’t check personally but from a paper by Sun, Liang, Wen, and Shum it appears that Adobe Illustrator and Corel Draw use a monotonic cubic spline interpolation instead of a linear interpolation. Then, when exporting to PostScript or PDF, a single Illustrator or Corel Draw patch gets exported as multiple Coons patches inorder to approximate the smooth transitions. The question then is: should the SVG standard support the Coons Patch meshes with bi-linear interpolation or should it specidfy a more complex interpolation. My inclination is to leave the interpolation as bi-linear and follow Adobe’s and Corel’s lead and let the authoring software handle smoothing out transitions when necessary. This keeps compatability with existing standards and keeps the definition of the patches simpler. More details about meshes in SVG can be found at my Coons Patche Meshes page.

SVG Kaleidoscopes

I’ve always loved kaleidoscopes. Here are a couple made by using Inkscape’s Tiled Clone dialog with hand animation. The animation is done with SMIL rather than JavaScript. The animations work in Chrome, Opera, and Firefox (although the performance of the latter is a bit poor). They will not work in IE as it does not (and never will according to the IE developers) support SMIL animation. (Why SMIL? It is easier to do simple animations and doesn’t get disabled by browsers due to security concerns.) Clicking on the kaleidoscopes will take you to a larger version. I’ve disabled the animation here as they eat too many CPU cycles. Click on images to go to full animated versions. A simple Kaleidoscope animation. A simple Kaleidoscope animation.

SVG and Browser Address Bar Trick

During a recent SVG Working Group meeting a question arose about current browser support for a particular SVG syntax. One of the group members pasted a quick one-line test case into the IRC meeting log and we were able to verify browser support by just pasting the line into the address bar. Try pasting:
data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg">
<rect x="20" y="20" width="100" height="50" fill="red"/></svg>
into the address bar of your browser. This works in Firefox, Opera, and Chrome. I haven’t checked IE.

Warped Text in Inkscape

I’ve been playing with different ways that Inkscape can be used to warp text and thought I would share a few images. This was all motivated by a discussion during an SVG working group meeting a couple of weeks ago on what the proper way to stretch glyphs when placed along a path. (At the moment only Opera can do it and it uses a rather simple algorithm.) You can find a more detailed discussion of this topic at my web site. The most successful experiments were those using the Envelope Deformation Live PathEffect. Only the top and bottom control paths were used (the right and left paths were disabled). For the text within circles, the circles were drawn using the Arc/Circle tool and then pasted in using the LPE editor. Note, you need to be using a modern browser capable of displaying SVG.
Text warped with Envelope LPE.
Text warped with Envelope LPE.
Text warped with Envelope LPE.
Text warped with Envelope LPE.
Text warped with Envelope LPE.

SVG display in Emacs

I got a surprise when opening an SVG file in emacs in Fedora 15 to do a little editing. I didn’t see the expected SVG source but instead saw a rendering of the SVG. Cool…. but one problem: How DO you edit the source? A quick Internet search led to aa Emacs Wiki page where the solution could be found: Use Ctrl-c Ctrl-c to switch back between editing and rendering modes. SVG rendering only works on a fairly recent version of emacs and only, it appears, on systems using X11. It uses the rather unloved librsvg2 library so don’t expect perfect rendering. The Wiki page also shows how you can control Inkscape directly from emacs if you have a DBUS enabled version of Inkscape. Hmm.

SVG Buttons in HTML (or SVG Integration in HTML)

It’s been awhile since I posted to this blog. I have been very busy getting the new edition of my Inkscape book ready for the publisher. I wanted to add a new tutorial on using SVG in HTML given that SVG is an integral part of the upcoming HTML5 standard and that IE will finally support SVG. Writing this tutorial turned out to be a lot more difficult than I had anticipated. Not only is there not a lot out there on how SVG fits into HTML5, but there are still major issues to be addressed by the standards groups. I wanted to start out the tutorial by creating a button that could be used as a better PNG. From there I planned to add functionality to the button such as keeping track of its state (i.e. is it on or off?). I also wanted to be able to style the button from HTML. An evolving web page documenting my trials and findings can be found at my Button Test page. Here I will just cover a few of the most important things I learned.

Using an SVG as a better PNG

The first problem I ran into is how to provide a PNG fallback for browsers that don’t support SVG. I wanted to simply replace a PNG button by an SVG button inside an <a> tag. The normal way to provide a PNG fallback is to use the <object> tag:
  
	<a href="http://tavmjong.free.fr/">
	  <object type="image/svg+xml" data="buttonA.svg">
	    <img src="buttonA.png" alt="A sample button."/>
	  </object>
	</a>
  
But this doesn’t work (except in IE9 beta) as the SVG “swallows” the mouse clicks when the button is pressed. They never bubble up to the <a> tag. This is probably by design for security reasons. Cameron Cameron McCormack from the SVG working group suggested using an error handler on an <img> tag. This does work (at least in IE8). So the first problem has been solved:
  
        <a href="http://tavmjong.free.fr/" target="_blank">
	  <img src="buttonA.svg" alt="A sample SVG button."
	       onerror="this.removeAttribute('onerror');
			this.src='buttonA.png'"/>
  
Ansample SVG button.

Reusing an SVG button on the same HTML page

After I added some functionality to the button via JavaScript (making it keep track of two different states), I faced the problem of how to reuse the button on the same page. When a button is clicked, the SVG script needs to notify the HTML script which instance of the button has been activated. At first it appeared that I would have to move the JavaScript code out of the SVG file and into the HTML file, as well as use an inline SVG wrapper to reference SVG fragments in the external SVG file. Erik Dahlström, also of the SVG working group, suggested that using window.frameElement.id inside the script in the SVG file would let you know which button was pushed. This id can then be passed to the script in the HTML file. This works quite well. This idea also lead to solving another problem: how to style the button from HTML. The SVG standard has a currentColor attribute/style parameter so one would think that one could specify the color in the <object>’s style attribute and the SVG file would pick it up. The SVG standard indicates that this is exactly the purpose of currentColor. Nope. CSS styling doesn’t work across document boundaries. But it is easy to get the color by using window.frameElement.style.color and then setting the button color in an init() function. One can go further. One can customize the text on the button by using <param>s inside the opening and closing <object> tags. The <param>s can also be grabbed by the SVG init() script. Here are two buttons using the same SVG file: Style from CSS (inside SVG) and custom text from <param>s:
  
    <object type="image/svg+xml" data="buttonG.svg" id="default">
      <param id="TextOn"   name="TextOn"  value="Green" />
      <param id="TextOff"  name="TextOff" value="Red" />
    </object>
  
If you don’t see a button: go to http://tavmjong.free.fr/blog/ The button text is OFF. Style from <object> and custom text from <param>s:
  
    <object type="image/svg+xml" data="buttonG.svg" id="pink" style="color:pink">
      <param id="TextOn"   name="TextOn"  value="I am on" />
      <param id="TextOff"  name="TextOff" value="I am off" />
    </object>
  
If you don’t see a button: go to http://tavmjong.free.fr/blog/ The button text is OFF.

SVG and Browser Support Part 3

Have you ever had a Zen moment? Like one where you finally know the sound of one hand clapping? I just had one. I now understand how SVG is suppose to be fitted into part of a web page (well almost, as you will see). This was not an easy task, and in fact I found it more difficult than understanding QCD. It took piecing together parts from nine sections in five different chapters and two versions of the SVG specification plus developing a test page. If you are a long time web developer (or standards writer) you probably already know how SVG is fitted into HTML, or could make a good guess; the problem is, I am not. The fact that the various browsers have rendering differences with SVG in HTML means that I am probably not alone. Why is this important? I have over 500 SVGs in my Inkscape book. I want the SVGs to scale to the same size as the PNG fallback images. It would be very time consuming to go through and size each one individually and DocBook doesn’t provide a way to scale them by a set factor automatically. The first step in placing SVG into HTML is determining the “viewport” (SVG1.1, 7.2). This is the region on the web page where the SVG is to be placed. The position of the viewport is determined by the HTML. The size can be specified by the HTML through “positioning properties” (SVG1.1, 7.2). For example, if a wrapping <object> tag has width and height attributes defined, they determine the viewport size. If, however, the wrapping tag does not specify a size, the width and height attributes in the SVG root are used (SVG1.1, 7.2). The SVG width and height can be in absolute units (e.g. px) in which case, that is the size of the viewport, or they can be defined in percentages, in which case things are more complicated. If width and height are both 100% (or not given), then the viewport will fill the space allocated by the wrapper. If width and height are less than 100% one would think that the viewport would be scaled down by that amount which seems consistent with SVG1.1, 6.16. However, SVG1.2Tiny, 7.14 states that if percentages are used, they correspond to the percentage of the viewport that is actually rendered and not the relative size of the viewport to the available area! This can explain why in some cases Firefox and Opera both show only a quarter of the SVG when width and height are both 50%. Firefox and Opera don’t agree when which rule should be applied. And in one case, Opera applies both rules, reducing the viewport and clipping the SVG content. The viewport has another role that may not be obvious at once. By default, the SVG is clipped by the viewport and not by the SVG width/height or viewBox (SVG1.1, 14.3.3 and 6.16). This means that if you leave an object outside the nominal area of your drawing it may show up when the SVG is embedded in HTML! Now that we have the viewport, the next step is transform the SVG to fit it. If there is no viewBox attribute, the SVG is rendered so that the origin (upper left corner) of the SVG is at the upper left corner of the viewport (SVG1.1, 7.3). One user unit in SVG space corresponds to one screen pixel (SVG1.1, 7.2). If the viewport is bigger than the allotted area, Firefox adds scroll bars, Opera does not. There is an attribute that might control the display of scrollbars, zoomAndPan (SVG1.1, 16.7), but it doesn’t appear used. If there is a viewBox, the viewBox is mapped to the viewport (SVG1.1, 7.7). How the mapping is done is determined by the preserveAspectRatio attribute. The default value is “xMidYMid meet” (SVG1.1, 5.1.2) which means that the center of the viewBox is at the center of the viewport and that the SVG is scaled uniformly so that one pair of sides (top/bottom or left/right) of the viewBox coincide with the viewport while the other pair of sides is inside the viewport (SVG1.1, 7.8). Now recall that if the SVG attributes width and height have percentage values less than 100% there may be some clipping involved. The most important thing to take away is that the SVG attributes width and height are not what a naive person might think. They are rather suggestions to the HTML layout engine about the area that should be allocated for the SVG and in which the SVG will be scaled to fit (using the viewPort and scaleAspectRatio attributes).

SVG and Browser Support Part 2

Now that I’ve determined the time to use SVGs in the online version of my Inkscape has come (see previous post), the question becomes what is the best way to do it? The primary concern is to provide a graceful fallback for browsers that don’t natively support SVGs or are missing some required SVG feature (e.g. lack of filter support in IE9 and Safari 5). There are some criteria for choosing which method to use. Since I do my illustrations in Inkscape, Javascript libraries like Dojo, Raphael, and JSXGraph that create SVG or VML content depending on the browser can immediately be ruled out. Another Javascript solution: SVGweb uses Flash to display content in browsers that don’t support SVG. I don’t like this solution for a number of reasons. I don’t want to require my readers to install Flash, I would like to avoid using Javascript, and I don’t want to pepper my HTML with [if IE] conditionals necessary to get the <object> tag to work in IE. There are a number of plug-ins that support SVG such as the original Adobe SVG viewer (ASV). I don’t want to require my readers to install plug-ins and none of the plug-ins are very good solutions (ASV, for example, is no longer supported in addition to having other problems like not supporting the <object> tag). Actually, there is one interesting plug-in, Google Chrome Frame (GCF). This plug-in can replace the renderer in IE6, IE7, or IE8 with the renderer from Chrome. By adding one <meta> tag to a web page (or making a small change to the server configuration) you can suggest that the page be rendered using GCF. No other changes to the HTML need to be made. If GCF is installed, it is used; if not, no harm done. Having eliminated the above options, we are left with using standard HTML or XHTML. There are five ways to include SVGs in HTML and XHTML, four of which we can easily dismiss:
  • Inline SVG: Requires XHTML or HTML5, neither which are supported by IE prior to IE9. In addition, as all my figures are in separate files, it makes no sense to inline them.
  • <img> tag: Doesn’t support interactive SVG. No fallback method.
  • <iframe> tag: On its way out in HTML4 and XHTML, but resurrected in HTML5. Intended in HTML5 to sandbox content from other sources. Again no fallback method.
  • <embed> tag: Never in any HTML or XHTML standard but widely supported. As a matter of practicality, included in HTML5. Intended for content that needs a plug-in (this was the method used by ASV). Again no fallback method.
  • <object> tag: In both HTML and XHTML standards. If the content referenced in the tag cannot be displayed, the content between the opening and closing <object> tags is exposed providing a simple fallback method. This is our obvious choice for including SVG content.
So, how does one use the <object> tag to provide fallback? Here is an example: <object type=”image/svg+xml” data=”svg_button.svg”> <img src=”svg_button.png” alt=”SVG Button”/> </object> SVG Button But this has one problem: it displays with scroll bars in Chrome 6. The scroll bars can be avoided by adding width and height to the <object> tag: <object type=”image/svg+xml” data=”svg_button.svg” width=”300px” height=”100px”> <img src=”svg_button.png” alt=”SVG Button”/> </object> SVG Button In fact, things get quite tricky with getting the SVG displayed correctly. All the browsers treat SVG included by the various tags differently as can be seen by this handy test page by Jeff Schiller. This is a known problem by the SVG working group and work is being done to clarify the correct behaviors. I am working on my own test pages to investigate SVG integration issues. There is an HTML version and an XHTML version. So we are almost there. The one things missing is what to do about the lack of SVG filter support in IE9 and Safari 5. That will be the topic of a future post.

SVG and Browser Support

My Inkscape book has hundreds of figures, all drawn with Inkscape and stored as SVGs (except screen shots, of course). In the online version of the book, all of the figures are presented as PNGs (with just a few exceptions). Wouldn’t it be great if they were presented as SVGs? When I started the book this wasn’t practical, SVG support in browsers was rather limited. But times have changed and with the imminent release of IE9 which includes native SVG support it is time to reevaluate if SVGs can be used. So what is the current market share for browsers that support SVGs? According to Jeff Schiller, the market share in July was 43%. But market share is strongly dependent on the type of content. It is interesting to see that the usage of both IE6 and IE7 drops by around 4% each during the weekend (while IE8 gains a little). This demonstrates IE6 and IE7 entrenchment in the workplace. Of course the most important data is for the actual users of the online Inkscape manual. Here are some statistics for the book users from last month:
Firefox 3.642.32 %
Internet Explorer 7.011.17 %
Internet Explorer 8.010.77 %
Safari 533.410.77 %
Safari 533.16.16 %
Firefox 3.54.66 %
Opera 9.83.25 %
Internet Explorer 6.02.94 %
Firefox 3.02.06 %
Safari 534.30.86 %
Safari 531.20.83 %
So about 70% of my book’s readers already can view SVG without using a plug-in. It seems that this is the time to start using SVGs. How to do this while still supporting non-SVG capable browsers is a topic for a later post.

Using SVG in WordPress

Now that I am blogging about Inkscape and SVG I needed to figure out how to use SVG with WordPress. A search of the Web revealed that it can be done… but not how. The first thing to try is using the <object> tag: <object id=”SVG Button” data=”http://tavmjong.free.fr/blog/wp-content/uploads/svg_button.svg” type=”image/svg+xml” width=”300″ height=”100″> <h1>Your browser does not support SVG! Too bad.</h1> <p>Using PNG fallback.</p> <img src=”http://tavmjong.free.fr/blog/wp-content/uploads/svg_button.png” alt=”Can’t display PNG Fallback”/> </object>

Your browser does not support SVG! Too bad.

Using PNG fallback.

Can't display PNG Fallback
This works! Added comments: Firefox 3.6 doesn’t hide the wrapped content unless everything is put on one line. Firefox 4beta doesn’t have this problem. IE8 thinks it has successfully displayed the SVG. Now we can try to use inlined SVG. This doesn’t work at first. A little experimentation shows that inlined SVG will work if the entire SVG is on one line (and if your browser has an HTML5 parser). Not too practical. A bit more experimentation shows that it will work if wrapped inside <pre> tags. The only problem with this method is that CSS styling is applied to the <pre> tag, shifting the SVG to the right and putting space above and below the SVG. Note: If your browser does not have an HTML5 parser, you’ll see a large box with just “SVG”.

  
    
      
      
      
    
    
      
      
      
        
        
      
    
    
  
  
  
  
  
  
  
    
    SVG