Skip to the Main Content

Note:These pages make extensive use of the latest XHTML and CSS Standards. They ought to look great in any standards-compliant modern browser. Unfortunately, they will probably look horrible in older browsers, like Netscape 4.x and IE 4.x. Moreover, many posts use MathML, which is, currently only supported in Mozilla. My best suggestion (and you will thank me when surfing an ever-increasing number of sites on the web which have been crafted to use the new standards) is to upgrade to the latest version of your browser. If that's not possible, consider moving to the Standards-compliant and open-source Mozilla browser.

February 4, 2008

foreignObject

MathML has been broken on Mozilla trunk for nearly 14 months now. I used to like running nightly builds of Firefox or SeaMonkey. But, since November 2006, my browser use has been frozen in amber.

Over the past several months, Karl Tomlinson has been toiling away fixing MathML on Mozilla trunk. And his efforts are definitely coming together. There are still a couple of rather serious layout bugs, and at least one æsthetic issue. But, with the release of the STIX fonts (you can still get a copy of the beta here), and various other improvements to the browser, I’ve been itching to get my hands on a version that had passable MathML support. Despite the remaining bugs, Firefox is good enough to begin playing around with.

One of the things I wanted to try out was the new support for SVG <foreignObject>, which, in particular, allows one to embed MathML fragments in SVG figures. In various posts of mine, I’ve been making occasional use of the converse ability, to embed SVG in MathML equations. But the n-Category Café guys would, I think, really profit from being able to create complicated commutative diagrams, etc., in SVG.

First, install the STIX fonts, and unset the font.mathfont-family preference that you probably set for previous versions. Now you can install the latest version.

Here’s an example, which should display correctly in Firefox3β3 and later:

Pairing of states as an (n-1) functor CC CC CC CC V xV_x V yV_y V xV_{x'} V yV_{y'} e 1(x)e_1(x) \Downarrow e 1(y)e_1(y) e¯ 2(x)\overline{e}_2(x') \Downarrow e¯ 2(y)\overline{e}_2(y') tra(γ 1)tra(\gamma_1) tra(Σ)\Downarrow tra(\Sigma) tra(γ 2)tra(\gamma_2) XX

It’s drawn from a blog entry by Urs, where there are quite a number of diagrams which would benefit from a similar treatment.

The markup used to create it,

<svg  xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="14.75em" height="17em" viewBox="0 -4 236 268">
 <desc>Pairing of states as an (n-1) functor</desc>
 <defs>
  <marker id="ttr295arrowhead" viewBox="0 0 10 10" refX="0" refY="5" markerUnits="strokeWidth" markerWidth="8" markerHeight="5" orient="auto">
   <path d="M 0 0 L 10 5 L 0 10 z"/>
  </marker>
 </defs>
 <path fill="#FEE" stroke="#000" stroke-dasharray="6" d="M19,8c25,8,110,34,196,1c26,97,20,130-1,198c-86,33-171,7-196-1c-26,-97,-20,-130,1,-198"/>
 <g fill="none" stroke="#000" marker-end="url(#ttr295arrowhead)">
  <path d="M106, 1h54"/>
  <path d="M68,256h54"/>
  <path d="M107,54c30-0.3,25,10,53,10"/>
  <path d="M69,196c30-0.3,25,10,53,10"/>
  <path d="M 58,210v33"/>
  <path d="M136,210v33"/>
  <path d="M 97,10v35"/>
  <path d="M176,10v35"/>
  <path d="M 97,68c0,54-41,36.3-41,118"/>
  <path d="M176,68c0,54-41,36.3-41,118"/>
 </g>
 <g font-size="14">
  <foreignObject x="92"  y="-10" width="16" height="20">$C$</foreignObject>
  <foreignObject x="172" y="-10" width="16" height="20">$C$</foreignObject>
  <foreignObject x="52"  y="246" width="16" height="20">$C$</foreignObject>
  <foreignObject x="132" y="246" width="16" height="20">$C$</foreignObject>
  <foreignObject x="92"   y="46" width="16" height="20">$V_x$</foreignObject>
  <foreignObject x="172"  y="50" width="16" height="20">$V_y$</foreignObject>
  <foreignObject x="51"  y="188" width="20" height="20">$V_{x'}$</foreignObject>
  <foreignObject x="131" y="192" width="20" height="20">$V_{y'}$</foreignObject>
  <foreignObject x="64"   y="22" width="34" height="20">$e_1(x)$</foreignObject>
  <foreignObject x="132"  y="26" width="16" height="24">$\Downarrow$</foreignObject>
  <foreignObject x="180"  y="18" width="32" height="20">$e_1(y)$</foreignObject>
  <foreignObject x="22"  y="220" width="40" height="20">$\overline{e}_2(x')$</foreignObject>
  <foreignObject x="90"  y="224" width="16" height="20">$\Downarrow$</foreignObject>
  <foreignObject x="140" y="224" width="36" height="20">$\overline{e}_2(y')$</foreignObject>
  <foreignObject x="36"  y="100" width="40" height="20">$tra(\gamma_1)$</foreignObject>
  <foreignObject x="128"  y="72" width="52" height="24" transform="rotate(20)">$\Downarrow tra(\Sigma)$</foreignObject>
  <foreignObject x="150" y="128" width="40" height="20">$tra(\gamma_2)$</foreignObject>
  <foreignObject x="200" y="188" width="36" height="20">$X$</foreignObject>
 </g>
</svg>

works in the comments, too. It’s kinda verbose, and so probably not all that much fun to generate. It would be great to have a more concise and intuitive pseudo-markup language to generate such things.

If you actually view source on the entry, you’ll see that the SVG that is ultimately spit out is even more (this time, unnecessarily) verbose, to keep the W3C Validator happy. I revised the SVGFix plugin for MovableType to add a <switch> as the parent of <foreignObject>, if one isn’t present already.

The same markup works in Instiki (which also required updating).

Here’s another example from the same post by Urs:

Complicated commutative diagram, realized in SVG 11 11 11 11 IdId IdId AA BB ρ\rho HH HH KK KK' ϕ 1\phi_1 ϕ 2\phi_2 N AN_A N BN_B N A N^\vee_A N B N^\vee_B

and the markup used to create it:

<svg xmlns="http://www.w3.org/2000/svg" width="18.75em" height="17.5em" viewBox="-30 -25 270 255">
 <desc>Complicated commutative diagram, realized in SVG</desc>
 <defs>
  <marker id="svg295arrowhead" viewBox="0 0 10 10" refX="0" refY="5" markerUnits="strokeWidth" markerWidth="8" markerHeight="5" orient="auto">
   <path d="M 0 0 L 10 5 L 0 10 z"/>
  </marker>
  <marker id="svg296arrowhead" viewBox="0 0 10 10" refX="0" refY="5" markerUnits="strokeWidth" markerWidth="6" markerHeight="4" orient="auto">
   <path d="M 0 0 L 10 5 L 0 10 z"/>
  </marker>
 </defs>
 <g font-size="14" markdown="1">
  <foreignObject x="53"  y="-11" width="16" height="22">$1$</foreignObject>
  <foreignObject x="155" y="-11" width="16" height="22">$1$</foreignObject>
  <foreignObject x="53"  y="192" width="16" height="22">$1$</foreignObject>
  <foreignObject x="155" y="192" width="16" height="22">$1$</foreignObject>
  <foreignObject x="220"  y="90" width="16" height="22">$Id$</foreignObject>
  <foreignObject x="-18"  y="90" width="16" height="22">$Id$</foreignObject>
  <foreignObject x="52"   y="90" width="16" height="22">$A$</foreignObject>
  <foreignObject x="155"  y="90" width="16" height="22">$B$</foreignObject>
  <foreignObject x="115"  y="90" width="16" height="22">$\rho$</foreignObject>
  <foreignObject x="97"  y="-19" width="16" height="22">$H$</foreignObject>
  <foreignObject x="97"  y="204" width="16" height="22">$H$</foreignObject>
  <foreignObject x="104"  y="46" width="16" height="22">$K$</foreignObject>
  <foreignObject x="104" y="137" width="16" height="22">$K'$</foreignObject>
  <foreignObject x="92"   y="21" width="18" height="22">$\phi_1$</foreignObject>
  <foreignObject x="110" y="159" width="18" height="22">$\phi_2$</foreignObject>
  <foreignObject x="35"   y="36" width="18" height="22">$N_A$</foreignObject>
  <foreignObject x="163"  y="36" width="18" height="22">$N_B$</foreignObject>
  <foreignObject x="32"  y="134" width="24" height="24">$N^\vee_A$</foreignObject>
  <foreignObject x="162" y="134" width="24" height="24">$N^\vee_B$</foreignObject>
 </g>
 <g fill="none" stroke="#000">
  <g marker-end="url(#svg295arrowhead)">
   <path d="M64.3,1H137"/>
   <path d="M159,11v67"/>
   <path d="M159,112.3v68"/>
   <path d="M56.3,112v68"/>
   <path d="M65,204.3h72"/>
   <path d="M56.3,11.3v67"/>
   <path d="M168.3,9c0,0,46,39.3,46,92.7s-36.7,85-36.7,85"/>
   <path d="M48,8.7c0,0-47,44.3-47,94s37.3,84,37.3,84"/>
   <path d="M63.3,112c0,0,16,27.3,44.7,27s39-20.6,39-20.6"/>
   <path d="M63.3,93.3C63.3,93.3,84,66,108,66s39,20.6,39,20.6"/>
  </g>
  <g stroke-width="2">
   <path stroke-width="4" d="M43,102.7H19.3"/>
   <path stroke="#FFF" d="M43,102.7H19.3" marker-end="url(#svg296arrowhead)"/>
   <path stroke-width="4" d="M205,102.7h-22"/>
   <path stroke="#FFF" d="M205,102.7h-22" marker-end="url(#svg296arrowhead)"/>
   <path stroke-width="4" d="M146,15.5l-72,55"/>
   <path stroke="#FFF" d="M146,15.5l-72,55" marker-end="url(#svg296arrowhead)"/>
   <path stroke-width="4" d="M147,126l-72,65"/>
   <path stroke="#FFF" d="M147,126l-72,65" marker-end="url(#svg296arrowhead)"/>
   <path stroke-width="4" d="M108,75v46"/>
   <path stroke="#FFF" d="M108,75v46" marker-end="url(#svg296arrowhead)"/>
  </g>
 </g>
</svg>

Hopefully, that’ll whet your appetite for the next release of Firefox, in which, surely, the remaining MathML rendering bugs will be fixed.

Update (2/5/2008):

One of the main advantages of using SVG is that it rescales nicely along with the text. Try changing the text zoom on this entry. Everything works nicely, except for <foreignObject> which, as you can see, breaks horribly. Is this Firefox’s implementation? My markup? Or is, as I am beginning to suspect, the Specification flawed? On closer inspection, I think this is a Gecko bug. When you zoom the text, the scaling seems to be applied twice: once to the <foreignOject> element and again to its <math> child, squaring the net scale-factor. (It’s this bug.)

By contrast, Rank-2 Symmetric Tensor Representation Fundamental Representation = Adjoint Representation Rank-3 Symmetric Tensor Representation \begin{svg} <svg xmlns="http://www.w3.org/2000/svg" width="1.875em" height="1em" viewBox="0 0 30 16"> <desc>Rank-2 Symmetric Tensor Representation</desc> <g transform="translate(5,5)" fill="#FCC" stroke="#000" stroke-width="2"> <rect width="10" height="10"/> <rect width="10" height="10" x="10"/> </g> </svg>\end{svg}\otimes\begin{svg} <svg xmlns="http://www.w3.org/2000/svg" width="1.875em" height="1em" viewBox="0 0 30 16"> <desc>Fundamental Representation</desc> <g transform="translate(5,5)" fill="#FCC" stroke="#000" stroke-width="2"> <rect width="10" height="10"/> </g> </svg> \end{svg}=\begin{svg} <svg xmlns="http://www.w3.org/2000/svg" width="1.875em" height="1.625em" viewBox="0 0 30 26"> <desc>Adjoint Representation</desc> <g transform="translate(5,5)" fill="#FCC" stroke="#000" stroke-width="2"> <rect width="10" height="10"/> <rect width="10" height="10" x="10"/> <rect width="10" height="10" y="10"/> </g> </svg>\end{svg}\oplus\begin{svg} <svg xmlns="http://www.w3.org/2000/svg" width="2.5em" height="1em" viewBox="0 0 40 16"> <desc>Rank-3 Symmetric Tensor Representation</desc> <g transform="translate(5,5)" fill="#FCC" stroke="#000" stroke-width="2"> <rect width="10" height="10"/> <rect width="10" height="10" x="10"/> <rect width="10" height="10" x="20"/> </g> </svg>\end{svg} (now that SVG’s can be sized in ems) rescales beautifully.

Posted by distler at February 4, 2008 2:49 PM

TrackBack URL for this Entry:   http://golem.ph.utexas.edu/cgi-bin/MT-3.0/dxy-tb.fcgi/1594

2 Comments & 2 Trackbacks

Re: foreignObject

Oddly enough, this page caused my FireFox 3b5 implementation to crash. I use XHTML+MathML+SVG, but I do not use prefix notation. This works for FireFox and Amaya. My dumb guess is that the .html extension causes Gecko to pass the page to the .html renderer, despite the server configuration of application/xhtml+xml. I thought I once read that Gecko does this because a lot of pages in the wild with the extension .html are actually tag soup despite the pplication/xhtml+xml claim. Of course, I am surely confused. The page does not crash Opera 9.5, but it cannot render the MathMl in the page.

Posted by: Dana Lee Ling on April 13, 2008 9:36 PM | Permalink | Reply to this

Re: foreignObject

I’d say, “file a bug.” But the page works fine for me (using a Trunk build).

And, no, the .html file extension does not take precedence over the Content-Type header (in any browser I know of).

Posted by: Jacques Distler on April 13, 2008 11:15 PM | Permalink | PGP Sig | Reply to this
Read the post WYSIWYG SVG Editing In Instiki
Weblog: Musings
Excerpt: Instiki+SVG-Edit
Tracked: February 12, 2010 1:57 AM
Read the post WYSIWYG SVG Editing In Instiki
Weblog: Sam Ruby
Excerpt: Jacques Distler:
Tracked: February 12, 2010 8:38 PM

Post a New Comment