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.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.Lack of smoothness in some cases can lead to visual artifacts as illustrated in the following figure: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: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: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.
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.
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.
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.
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 PNGThe 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:
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/"> <object type="image/svg+xml" data="buttonA.svg"> <img src="buttonA.png" alt="A sample button."/> </object> </a>
<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'"/>
window.frameElement.idinside the script in the SVG file would let you know which button was pushed. This
idcan 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
currentColorattribute/style parameter so one would think that one could specify the
colorin 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.colorand 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:
The button text is OFF. Style from <object> 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>
The button text is OFF.
<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>
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).
- 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.
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:
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.
|Firefox 3.6||42.32 %|
|Internet Explorer 7.0||11.17 %|
|Internet Explorer 8.0||10.77 %|
|Safari 533.4||10.77 %|
|Safari 533.1||6.16 %|
|Firefox 3.5||4.66 %|
|Opera 9.8||3.25 %|
|Internet Explorer 6.0||2.94 %|
|Firefox 3.0||2.06 %|
|Safari 534.3||0.86 %|
|Safari 531.2||0.83 %|
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> This works! 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”.